pax_global_header00006660000000000000000000000064145671063210014517gustar00rootroot0000000000000052 comment=5e72b9d99eaea55fe87eb8ac945ec9e914a69327 msolve-0.6.5/000077500000000000000000000000001456710632100130345ustar00rootroot00000000000000msolve-0.6.5/.github/000077500000000000000000000000001456710632100143745ustar00rootroot00000000000000msolve-0.6.5/.github/workflows/000077500000000000000000000000001456710632100164315ustar00rootroot00000000000000msolve-0.6.5/.github/workflows/msolve.yml000066400000000000000000000020351456710632100204610ustar00rootroot00000000000000name: msolve CI on: push: branches: [ "master" ] pull_request: branches: [ "master" ] jobs: build: runs-on: ${{ matrix.os }} timeout-minutes: 10 strategy: fail-fast: false matrix: os: - ubuntu-latest - macos-latest steps: - uses: actions/checkout@v3 - name: "Install dependencies" run: | if [ "$RUNNER_OS" == "Linux" ]; then # sharutils is for uudecode sudo apt install libgmp-dev libflint-dev libmpfr-dev libntl-dev elif [ "$RUNNER_OS" == "macOS" ]; then brew install autoconf automake libtool gmp flint mpfr ntl else echo "$RUNNER_OS not supported" exit 1 fi - name: autogen run: ./autogen.sh - name: configure run: ./configure - name: make run: make - name: make check run: make check - name: make distcheck run: make distcheck msolve-0.6.5/.gitignore000066400000000000000000000005171456710632100150270ustar00rootroot00000000000000*.a *.o *.so *.lo *.la *.log *.trs *~ *.libs *.in *.m4 *Makefile *Makefile.in *.deps *.dirstamp aclocal.m4 ar-lib autom4te.cache/ autoscan.log compile config.guess config.h config.h.in config.log config.status config.sub configure configure.ac.bak configure.scan depcomp install-sh libtool ltmain.sh missing stamp-h1 msolve.pc /msolve msolve-0.6.5/AUTHORS000066400000000000000000000001701456710632100141020ustar00rootroot00000000000000Jérémy Berthomieu (Sorbonne Université) Christian Eder (TU Kaiserslautern) Mohab Safey El Din (Sorbonne Université) msolve-0.6.5/COPYING000066400000000000000000000432541456710632100140770ustar00rootroot00000000000000 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. msolve-0.6.5/INSTALL000066400000000000000000000030161456710632100140650ustar00rootroot00000000000000If you are working with the git repository ========================================== You will need to have autotools installed on your system. 1. Run `./autogen.sh` which generates configure and the Makefiles. 2. Run `./configure` (possibly with options, see `./configure -h` for more information). 3. Run `make` (possibly with CFLAGS and LDFLAGS adjusted). 4. Run `make check`. 5. Run `make install` in order to globally install the library and the binary of msolve. If you are working on a distriubtion (downloaded *.tar.gz) ========================================================== 1. Run `./configure` (possibly with options, see ./configure -help for more information). 2. Run `make` (possibly with CFLAGS and LDFLAGS adjusted). 3. Run `make check`. 4. Run `make install` in order to globally install the library and the binary of msolve. NOTE TO MAC OS users ==================== To build a static binary file, you may need to run `./configure -static`. You may also need to proceed slightly differently by modifying the `Makefile` file as follows - add to the `LIBS` variable the `-fopenmp` option ``` LIBS = -lflint -lmpfr -lgmp -lm -fopenmp ``` - change the `CC` variable to your actual `gcc` compiler, e.g. ``` CC = gcc-11 ``` since `gcc` seems to be linked to `clang`. If you want to generate a distribution ====================================== Run `make dist`. If you want to generate a static binary ======================================= Add `-all-static` to your LDFLAGS as follows `make LDFLAGS="-all-static"`. msolve-0.6.5/Makefile.am000066400000000000000000000043741456710632100151000ustar00rootroot00000000000000AUTOMAKE_OPTIONS = color-tests SUBDIRS = src/usolve src/fglm src/neogb src/msolve AM_CFLAGS = $(SIMD_FLAGS) $(CPUEXT_FLAGS) $(OPENMP_CFLAGS) LDADD = src/neogb/libneogb.la src/fglm/libfglm.la src/usolve/libusolve.la bin_PROGRAMS = msolve msolve_SOURCES = src/msolve/main.c check_PROGRAMS = neogb_io \ fglm_build_matrixn_radical_shape-31 \ fglm_build_matrixn_nonradical_shape-31 \ fglm_build_matrixn_nonradical_radicalshape-31 checkdiff = test/diff/diff_cp_d_3_n_4_p_2.sh \ test/diff/diff_eco11-31.sh \ test/diff/diff_truncate_gb.sh \ test/diff/diff_elim-31.sh \ test/diff/diff_elim-qq.sh \ test/diff/diff_F4SAT-31.sh \ test/diff/diff_F4SAT-byone-31.sh \ test/diff/diff_kat6-31.sh \ test/diff/diff_kat7-qq.sh \ test/diff/diff_multy-16.sh \ test/diff/diff_multy-31.sh \ test/diff/diff_multy-qq.sh \ test/diff/diff_nonradical_shape-qq.sh \ test/diff/diff_nonradical_radicalshape-qq.sh \ test/diff/diff_nonradical_radicalshape-no-square-31.sh \ test/diff/diff_nonradical_radicalshape-no-square-qq.sh \ test/diff/diff_one-16.sh \ test/diff/diff_one-31.sh \ test/diff/diff_one-qq.sh \ test/diff/diff_radical_shape-31.sh \ test/diff/diff_radical_shape-qq.sh \ test/diff/diff_reals_dim0.sh \ test/diff/diff_reals_extract.sh \ test/diff/diff_reals_dim0-swapvar.sh \ test/diff/diff_reals_dim0-chgvar.sh \ test/diff/diff_bug_empty_tracer.sh \ test/diff/diff_bug_2nd_prime_bad.sh \ test/diff/diff_bug_68.sh \ test/diff/diff_mq_2_1.sh \ test/diff/diff_xy-qq.sh \ test/diff/diff_input-overflow-16.sh \ test/diff/diff_nf_8.sh \ test/diff/diff_nf_16.sh \ test/diff/diff_nf_31.sh \ test/diff/diff_nf_lm_bug.sh # dist_check_DATA = test/input_files neogb_io_SOURCES = test/neogb/io/validate_input_data.c fglm_build_matrixn_radical_shape_31_SOURCES = test/fglm/build_matrixn_radical_shape-31.c fglm_build_matrixn_nonradical_shape_31_SOURCES = test/fglm/build_matrixn_nonradical_shape-31.c fglm_build_matrixn_nonradical_radicalshape_31_SOURCES = test/fglm/build_matrixn_nonradical_radicalshape-31.c TESTS = $(check_PROGRAMS) $(checkdiff) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = msolve.pc msolve-0.6.5/README.md000066400000000000000000000227321456710632100143210ustar00rootroot00000000000000# MSOLVE: Multivariate polynomial system solver | **Documentation** | |:-------------------------------------------------------------------------:| | [![][docs-stable-img]][docs-stable-url] [![][docs-dev-img]][docs-dev-url] | [https://msolve.lip6.fr/](https://msolve.lip6.fr) `msolve` is an open source C library implementing computer algebra algorithms for solving polynomial systems (with rational coefficients or coefficients in a prime field). Currently, with `msolve`, you can basically solve multivariate polynomial systems. This encompasses: * the computation of **Groebner bases** * **real root isolation of the solutions** to polynomial systems * the computation of the dimension and the degree of the solution set and many other things you can do using msolve. A tutorial is available [here](https://msolve.lip6.fr/downloads/msolve-tutorial.pdf) Some of the functionalities of [msolve](https://msolve.lip6.fr) are already available in the computer algebra systems [Oscar](https://oscar-system.github.io/Oscar.jl) and [SageMath](https://sagemath.org). See below for some more information about this. # Install Instructions See the INSTALL file. # Input File Format More informations are given in the tutorial (see [https://msolve.lip6.fr](https://msolve.lip6.fr)) `msolve` input files need to be of the following format: **1st line**: variables as commata separated list, e.g. `x1,x2,x3,x4,y1,y2`.
**2nd line**: field characteristic, e.g. `0`.
**following lines**: generating polynomials, all but the last one need to terminate by a `,`, e.g. ``` x1,x2,x3,x4,y1,y2 101 x1+x2+x3+x4, 2*y1-145*y2 ``` Polynomials may be multiline, thus `,` as a separator. Coefficients can be rational, using `/`, e.g. `-2/3*x2*y1^2+...`. # Basic usage Some basic commands are as follows: ``` ./msolve -f in.ms -o out.ms ``` will: - detect if the input system has dimension at most 0 - when the system has dimension at most 0 and the coefficients are rational numbers, `msolve` will isolate the real solutions - when the system has dimension at most 0 and the coefficients are in a prime field, `msolve` will compute a parametrization of the solutions All output data are displayed in the file `out.ms` The `-v`flag allows you to control the verbosity, giving insight on what `msolve` is doing. Try this. ``` ./msolve -v 2 -f in.ms -o out.ms ``` # Computing Groebner bases `msolve` computes Groebner bases when the base field is either the field of rational numbers or a prime field (characteristic should be less than 2^31). The following command ``` ./msolve -g 1 -f in.ms -o out.ms ``` will compute the leading monomials of the reduced Groebner basis of the ideal generated by the input system in `in.ms` for the so-called graded reverse lexicographic ordering. This allows you to deduce the dimension of the solution set to the input polynomials (in an algebraic closure of the base field) as well as the degree of the ideal they generate. Using the `-g 2` flag as follows ``` ./msolve -g 2 -f in.ms -o out.ms ``` will return the reduced Groebner basis for the graded reverse lexicographic ordering. `msolve` also allows you to perform Groebner bases computations using **one-block elimination monomial order** thanks to the `-e` flag. The following command ``` ./msolve -e 1 -g 2 -f in.ms -o out.ms ``` will perform the Groebner basis computation eliminating the first variable. More generally, using `-e k` will eliminate the first `k` variables. # Solving over the real numbers When the input polynomial system has rational coefficients and when *it has finitely many complex solutions*, `msolve` will, by default, compute the real solutions to the input system. Those are encoded with isolating boxes for all coordinates to all real solutions. For instance, on input file `in.ms` as follows ``` x, y 0 x^2+y^2-4, x*y-1 ``` the call `./msolve -f in.ms -o out.ms` will display in the file `out.ms` the following output ``` [0, [1, [[[-41011514734338452707966945920 / 2^96, -41011514734338452707966945917 / 2^96], [-153057056683910732545430822374 / 2^96, -153057056683910732545430822373 / 2^96]], [[-612228226735642930181723289497 / 2^98, -612228226735642930181723289492 / 2^98], [-164046058937353810831867783675 / 2^98, -164046058937353810831867783674 / 2^98]], [[612228226735642930181723289492 / 2^98, 612228226735642930181723289497 / 2^98], [164046058937353810831867783674 / 2^98, 164046058937353810831867783675 / 2^98]], [[41011514734338452707966945917 / 2^96, 41011514734338452707966945920 / 2^96], [153057056683910732545430822373 / 2^96, 153057056683910732545430822374 / 2^96]]] ]]: ``` which are the 4 isolating boxes of the 4 exact roots whose numerical approximations are `(-0.5176380902, -1.931851653)`, `(-1.931851653, -0.5176380902)`, `(1.931851653, 0.5176380902)` and `(0.5176380902, 1.931851653)`. # Multi-threading Several components of `msolve` are parallelized through multi-threading. Typing ``` ./msolve -t 4 -f in.ms -o out.ms ``` tells `msolve` to use 4 threads. Multi-threading in `msolve` is used in - linear algebra algorithms used for Groebner bases computations over prime fields - multi-modular computations for solving over the reals (all intermediate and independent prime computations are run in parallel) - algorithms for real root isolation. # `msolve` in [AlgebraicSolving](https://github.com/algebraic-solving/AlgebraicSolving.jl) [AlgebraicSolving](https://github.com/algebraic-solving/AlgebraicSolving.jl) is a Julia package that wraps `msolve` and provides some more functionality like computing rational solutions. See [here](https://algebraic-solving.github.io/) for more information and documentation. # `msolve` in [Oscar](https://oscar-system.github.io/Oscar.jl) `msolve` is used in [Oscar](https://oscar-system.github.io/Oscar.jl) to *solve* polynomial systems with rational coefficients. It will detect if the input system has finitely many complex solutions, in which case it will output a rational parametrization of the solution set as well as the real solutions to the input system (see `msolve`'s tutorial [here](https://msolve.lip6.fr/downloads/msolve-tutorial.pdf)). You can have a look at [this](https://github.com/oscar-system/Oscar.jl/blob/master/src/Rings/solving.jl) and the documentation of [Oscar](https://oscar-system.github.io/Oscar.jl). Here is how you can use it. ```jldoctest julia> R,(x1,x2,x3) = PolynomialRing(QQ, ["x1","x2","x3"]) (Multivariate Polynomial Ring in x1, x2, x3 over Rational Field, fmpq_mpoly[x1, x2, x3]) julia> I = ideal(R, [x1+2*x2+2*x3-1, x1^2+2*x2^2+2*x3^2-x1, 2*x1*x2+2*x2*x3-x2]) ideal(x1 + 2*x2 + 2*x3 - 1, x1^2 - x1 + 2*x2^2 + 2*x3^2, 2*x1*x2 + 2*x2*x3 - x2) julia> real_solutions(I) ((84*x^4 - 40*x^3 + x^2 + x, 336*x^3 - 120*x^2 + 2*x + 1, PolyElem[-184*x^3 + 80*x^2 - 4*x - 1, -36*x^3 + 18*x^2 - 2*x], fmpz[-1, -1]), Vector{fmpq}[[744483363399261433351//1180591620717411303424, 372241681699630716673//1180591620717411303424, -154187553040555781639//1180591620717411303424], [1, 0, 0], [71793683196126133110381699745//316912650057057350374175801344, 71793683196126133110381699745//633825300114114700748351602688, 173325283664805084153412401855//633825300114114700748351602688], [196765270119568550571//590295810358705651712, 1//590295810358705651712, 196765270119568550571//590295810358705651712]]) ``` # `msolve` in [SageMath](https://sagemath.org) When you have `msolve` installed, it is used by [SageMath](https://sagemath.org) when you call the `Variety` function for solving polynomial systems with real coefficients. You can have a look [here](https://github.com/sagemath/sage/blob/develop/src/sage/rings/polynomial/msolve.py) and [here](https://github.com/sagemath/sage/blob/develop/src/sage/rings/polynomial/multi_polynomial_ideal.py) We are grateful to Marc Mezzarobba who initiated the usage of `msolve`in [SageMath](https://sagemath.org) and the whole development team of [SageMath](https://sagemath.org), in particular those involed in this [ticket](https://trac.sagemath.org/ticket/33734) # Citing `msolve` If you have used `msolve` in the preparation of some paper, we are grateful that you cite it as follows: ``` msolve: A Library for Solving Polynomial Systems, J. Berthomieu, C. Eder, M. Safey El Din, Proceedings of the 46th International Symposium on Symbolic and Algebraic Computation (ISSAC), pp. 51-58, ACM, 2021. ``` or, if you use BibTeX entries: ``` @inproceedings{msolve, TITLE = {{msolve: A Library for Solving Polynomial Systems}}, AUTHOR = {Berthomieu, J{\'e}r{\'e}my and Eder, Christian and {Safey El Din}, Mohab}, BOOKTITLE = {{2021 International Symposium on Symbolic and Algebraic Computation}}, ADDRESS = {Saint Petersburg, Russia}, SERIES = {46th International Symposium on Symbolic and Algebraic Computation}, PAGES = {51--58}, PUBLISHER = {{ACM}}, YEAR = {2021}, MONTH = Jul, DOI = {10.1145/3452143.3465545}, PDF = {https://hal.sorbonne-universite.fr/hal-03191666v2/file/main.pdf}, HAL_ID = {hal-03191666}, HAL_VERSION = {v2}, } ``` The paper can be downloaded [here](https://hal.sorbonne-universite.fr/hal-03191666v2/file/main.pdf). [docs-dev-img]: https://img.shields.io/badge/docs-dev-blue.svg [docs-dev-url]: https://msolve.lip6.fr/downloads/msolve-tutorial.pdf [docs-stable-img]: https://img.shields.io/badge/docs-stable-blue.svg [docs-stable-url]: https://msolve.lip6.fr/downloads/msolve-tutorial.pdf # Funding The development of `msolve` is supported by the [Forschungsinitiative Rheinland-Pfalz](https://rptu.de/forschung/forschungsinitiative-rlp). msolve-0.6.5/autogen.sh000077500000000000000000000000321456710632100150300ustar00rootroot00000000000000#!/bin/sh autoreconf -fiv msolve-0.6.5/configure.ac000066400000000000000000000224461456710632100153320ustar00rootroot00000000000000# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) AC_INIT([msolve], [0.6.5], [ederc@mathematik.uni-kl.de,mohab.safey@lip6.fr]) AM_INIT_AUTOMAKE([-Wall -Werror foreign silent-rules subdir-objects color-tests parallel-tests]) AC_CONFIG_SRCDIR([config.h.in]) AC_CONFIG_MACRO_DIR([m4]) AM_MAINTAINER_MODE AM_PROG_AR LT_INIT # Checks for programs. AC_PROG_CC # Checks for libraries. # CAUTION: Order matters for static binary building. AC_SEARCH_LIBS([atan2],[m], [], [AC_MSG_ERROR(["The C math library was not found!"])]) AC_SEARCH_LIBS([__gmpz_init],[gmp], [], [AC_MSG_ERROR(["GMP library was not found."])]) AC_SEARCH_LIBS([mpfr_init],[mpfr], [], [AC_MSG_ERROR([MPFR library was not found.])]) AC_SEARCH_LIBS([fmpz_add_ui],[flint], [], [AC_MSG_ERROR([FLINT library was not found.])]) # check if we want OpenMP support AC_ARG_ENABLE([openmp], [ --enable-openmp Enable OpenMP support], [case "${enableval}" in yes) openmp=true ;; no) openmp=false ;; *) AC_MSG_ERROR([bad value ${enableval} for --enable-openmp]) ;; esac],[openmp=true]) if test x$openmp = xtrue ; then AC_OPENMP fi # Checks for header files. AC_CHECK_HEADERS([inttypes.h stdint.h sys/time.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_INLINE AC_TYPE_INT16_T AC_TYPE_INT32_T AC_TYPE_INT64_T AC_TYPE_INT8_T AC_TYPE_SIZE_T AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_UINT8_T AX_COUNT_CPUS AX_EXT AX_GCC_BUILTIN([__builtin_constant_p]) AX_GCC_BUILTIN([__builtin_clzll]) AX_GCC_BUILTIN([__builtin_clzl]) # Checks for library functions. AC_FUNC_MALLOC AC_FUNC_REALLOC AC_CHECK_FUNCS([floor getdelim gettimeofday memmove memset pow sqrt strchr strstr strtol]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([ Makefile msolve.pc src/fglm/Makefile src/neogb/Makefile src/usolve/Makefile src/msolve/Makefile ]) AC_CONFIG_LINKS([ test/diff/diff_source.sh:test/diff/diff_source.sh input_files/cp_d_3_n_4_p_2.ms:input_files/cp_d_3_n_4_p_2.ms output_files/cp_d_3_n_4_p_2.res:output_files/cp_d_3_n_4_p_2.res test/diff/diff_cp_d_3_n_4_p_2.sh:test/diff/diff_cp_d_3_n_4_p_2.sh input_files/eco11-31.ms:input_files/eco11-31.ms output_files/eco11-31.res:output_files/eco11-31.res test/diff/diff_eco11-31.sh:test/diff/diff_eco11-31.sh input_files/elim-31.ms:input_files/elim-31.ms output_files/elim-31.res:output_files/elim-31.res output_files/elim-31.e2.res:output_files/elim-31.e2.res test/diff/diff_elim-31.sh:test/diff/diff_elim-31.sh input_files/elim-qq.ms:input_files/elim-qq.ms output_files/elim-qq.res:output_files/elim-qq.res output_files/elim-qq.e2.res:output_files/elim-qq.e2.res test/diff/diff_elim-qq.sh:test/diff/diff_elim-qq.sh input_files/F4SAT-31.ms:input_files/F4SAT-31.ms output_files/F4SAT-31.res:output_files/F4SAT-31.res test/diff/diff_F4SAT-31.sh:test/diff/diff_F4SAT-31.sh input_files/F4SAT-byone-31.ms:input_files/F4SAT-byone-31.ms output_files/F4SAT-byone-31.res:output_files/F4SAT-byone-31.res test/diff/diff_F4SAT-byone-31.sh:test/diff/diff_F4SAT-byone-31.sh input_files/kat6-31.ms:input_files/kat6-31.ms output_files/kat6-31.res:output_files/kat6-31.res test/diff/diff_kat6-31.sh:test/diff/diff_kat6-31.sh input_files/kat7-qq.ms:input_files/kat7-qq.ms output_files/kat7-qq.res:output_files/kat7-qq.res test/diff/diff_kat7-qq.sh:test/diff/diff_kat7-qq.sh input_files/multy-16.ms:input_files/multy-16.ms output_files/multy-16.res:output_files/multy-16.res test/diff/diff_multy-16.sh:test/diff/diff_multy-16.sh input_files/multy-31.ms:input_files/multy-31.ms output_files/multy-31.res:output_files/multy-31.res test/diff/diff_multy-31.sh:test/diff/diff_multy-31.sh input_files/multy-qq.ms:input_files/multy-qq.ms output_files/multy-qq.res:output_files/multy-qq.res test/diff/diff_multy-qq.sh:test/diff/diff_multy-qq.sh input_files/nonradical_shape-31.ms:input_files/nonradical_shape-31.ms output_files/nonradical_shape-31.res:output_files/nonradical_shape-31.res input_files/nonradical_shape-qq.ms:input_files/nonradical_shape-qq.ms output_files/nonradical_shape-qq.res:output_files/nonradical_shape-qq.res output_files/nonradical_shape-qq.p1024.res:output_files/nonradical_shape-qq.p1024.res test/diff/diff_nonradical_shape-qq.sh:test/diff/diff_nonradical_shape-qq.sh input_files/nonradical_radicalshape-31.ms:input_files/nonradical_radicalshape-31.ms output_files/nonradical_radicalshape-31.res:output_files/nonradical_radicalshape-31.res input_files/nonradical_radicalshape-qq.ms:input_files/nonradical_radicalshape-qq.ms output_files/nonradical_radicalshape-qq.res:output_files/nonradical_radicalshape-qq.res output_files/nonradical_radicalshape-qq.p3.res:output_files/nonradical_radicalshape-qq.p3.res test/diff/diff_nonradical_radicalshape-qq.sh:test/diff/diff_nonradical_radicalshape-qq.sh input_files/nonradical_radicalshape-no-square-31.ms:input_files/nonradical_radicalshape-no-square-31.ms output_files/nonradical_radicalshape-no-square-31.c0.res:output_files/nonradical_radicalshape-no-square-31.c0.res test/diff/diff_nonradical_radicalshape-no-square-31.sh:test/diff/diff_nonradical_radicalshape-no-square-31.sh input_files/nonradical_radicalshape-no-square-qq.ms:input_files/nonradical_radicalshape-no-square-qq.ms output_files/nonradical_radicalshape-no-square-qq.res:output_files/nonradical_radicalshape-no-square-qq.res output_files/nonradical_radicalshape-no-square-qq.p3.res:output_files/nonradical_radicalshape-no-square-qq.p3.res test/diff/diff_nonradical_radicalshape-no-square-qq.sh:test/diff/diff_nonradical_radicalshape-no-square-qq.sh input_files/one-16.ms:input_files/one-16.ms output_files/one-16.res:output_files/one-16.res test/diff/diff_one-16.sh:test/diff/diff_one-16.sh input_files/kat8-qq-truncate.ms:input_files/kat8-qq-truncate.ms output_files/kat8-qq-truncate.res:output_files/kat8-qq-truncate.res test/diff/diff_truncate_gb.sh:test/diff/diff_truncate_gb.sh input_files/one-31.ms:input_files/one-31.ms output_files/one-31.res:output_files/one-31.res test/diff/diff_one-31.sh:test/diff/diff_one-31.sh input_files/one-qq.ms:input_files/one-qq.ms output_files/one-qq.res:output_files/one-qq.res output_files/one-qq.g2.res:output_files/one-qq.g2.res test/diff/diff_one-qq.sh:test/diff/diff_one-qq.sh input_files/radical_shape-31.ms:input_files/radical_shape-31.ms output_files/radical_shape-31.res:output_files/radical_shape-31.res test/diff/diff_radical_shape-31.sh:test/diff/diff_radical_shape-31.sh input_files/radical_shape-qq.ms:input_files/radical_shape-qq.ms output_files/radical_shape-qq.res:output_files/radical_shape-qq.res test/diff/diff_radical_shape-qq.sh:test/diff/diff_radical_shape-qq.sh input_files/reals_dim0.ms:input_files/reals_dim0.ms output_files/reals_dim0.res:output_files/reals_dim0.res output_files/reals_dim0.p256.res:output_files/reals_dim0.p256.res test/diff/diff_reals_dim0.sh:test/diff/diff_reals_dim0.sh input_files/realroot-extract.ms:input_files/realroot-extract.ms output_files/realroot-extract.res:output_files/realroot-extract.res output_files/realroot-extract.p256.res:output_files/realroot-extract.p256.res test/diff/diff_reals_extract.sh:test/diff/diff_reals_extract.sh input_files/bug-chgvar.ms:input_files/bug-chgvar.ms output_files/bug-chgvar.res:output_files/bug-chgvar.res output_files/bug-chgvar.p256.res:output_files/bug-chgvar.p256.res test/diff/diff_reals_dim0-chgvar.sh:test/diff/diff_reals_dim0-chgvar.sh input_files/reals_dim0-swapvar.ms:input_files/reals_dim0-swapvar.ms output_files/reals_dim0-swapvar.res:output_files/reals_dim0-swapvar.res output_files/reals_dim0-swapvar.p256.res:output_files/reals_dim0-swapvar.p256.res test/diff/diff_reals_dim0-swapvar.sh:test/diff/diff_reals_dim0-swapvar.sh input_files/bug-empty-tracer.ms:input_files/bug-empty-tracer.ms output_files/bug-empty-tracer.res:output_files/bug-empty-tracer.res test/diff/diff_bug_empty_tracer.sh:test/diff/diff_bug_empty_tracer.sh input_files/bug-2nd-prime-bad.ms:input_files/bug-2nd-prime-bad.ms output_files/bug-2nd-prime-bad.res:output_files/bug-2nd-prime-bad.res test/diff/diff_bug_2nd_prime_bad.sh:test/diff/diff_bug_2nd_prime_bad.sh input_files/xy-qq.ms:input_files/xy-qq.ms output_files/xy-qq.res:output_files/xy-qq.res test/diff/diff_xy-qq.sh:test/diff/diff_xy-qq.sh input_files/bug_68.ms:input_files/bug_68.ms output_files/bug_68.res:output_files/bug_68.res test/diff/diff_bug_68.sh:test/diff/diff_bug_68.sh input_files/mq_2_1.ms:input_files/mq_2_1.ms output_files/mq_2_1.res:output_files/mq_2_1.res test/diff/diff_mq_2_1.sh:test/diff/diff_mq_2_1.sh input_files/input-overflow-16.ms:input_files/input-overflow-16.ms output_files/input-overflow-16.res:output_files/input-overflow-16.res test/diff/diff_input-overflow-16.sh:test/diff/diff_input-overflow-16.sh input_files/nf-8.ms:input_files/nf-8.ms output_files/nf-8.res:output_files/nf-8.res test/diff/diff_nf_8.sh:test/diff/diff_nf_8.sh input_files/nf-16.ms:input_files/nf-16.ms output_files/nf-16.res:output_files/nf-16.res test/diff/diff_nf_16.sh:test/diff/diff_nf_16.sh input_files/nf-31.ms:input_files/nf-31.ms output_files/nf-31.res:output_files/nf-31.res test/diff/diff_nf_31.sh:test/diff/diff_nf_31.sh input_files/nf-lm-bug.ms:input_files/nf-lm-bug.ms output_files/nf-lm-bug.res:output_files/nf-lm-bug.res test/diff/diff_nf_lm_bug.sh:test/diff/diff_nf_lm_bug.sh ]) AC_OUTPUT msolve-0.6.5/doc/000077500000000000000000000000001456710632100136015ustar00rootroot00000000000000msolve-0.6.5/doc/biblio.bib000066400000000000000000000407311456710632100155240ustar00rootroot00000000000000@inproceedings{msolve, TITLE = {{msolve: A Library for Solving Polynomial Systems}}, AUTHOR = {Berthomieu, J{\'e}r{\'e}my and Eder, Christian and {Safey El Din}, Mohab}, URL = {https://hal.sorbonne-universite.fr/hal-03191666}, BOOKTITLE = {{2021 International Symposium on Symbolic and Algebraic Computation}}, ADDRESS = {Saint Petersburg, Russia}, SERIES = {46th International Symposium on Symbolic and Algebraic Computation}, YEAR = {2021}, MONTH = Jul, DOI = {10.1145/3452143.3465545}, PDF = {https://hal.sorbonne-universite.fr/hal-03191666v2/file/main.pdf}, HAL_ID = {hal-03191666}, HAL_VERSION = {v2}, } @article{SparseFGLM, title = "Sparse {FGLM} algorithms", journal = "Journal of Symbolic Computation", volume = "80", pages = "538--569", year = "2017", issn = "0747-7171", doi = "https://doi.org/10.1016/j.jsc.2016.07.025", url = "http://www.sciencedirect.com/science/article/pii/S0747717116300700", author = "Jean-{\relax Ch}arles Faug{\`e}re and Chenqi Mou", keywords = "Gröbner bases, Change of ordering, Zero-dimensional ideal, Sparse matrix, Wiedemann algorithm, algorithm", abstract = "Given a zero-dimensional ideal I⊂K[x1,…,xn] of degree D, the transformation of the ordering of its Gröbner basis from DRL to LEX is a key step in polynomial system solving and turns out to be the bottleneck of the whole solving process. Thus it is of crucial importance to design efficient algorithms to perform the change of ordering. The main contributions of this paper are several efficient methods for the change of ordering which take advantage of the sparsity of multiplication matrices in the classical FGLM algorithm. Combining all these methods, we propose a deterministic top-level algorithm that automatically detects which method to use depending on the input. As a by-product, we have a fast implementation that is able to handle ideals of degree over 60000. Such an implementation outperforms the Magma and Singular ones, as shown by our experiments. First for the shape position case, two methods are designed based on the Wiedemann algorithm: the first is probabilistic and its complexity to complete the change of ordering is O(D(N1+nlog⁡(D)2)), where N1 is the number of nonzero entries of a multiplication matrix; the other is deterministic and computes the LEX Gröbner basis of I via Chinese Remainder Theorem. Then for the general case, the designed method is characterized by the Berlekamp--Massey--Sakata algorithm from Coding Theory to handle the multi-dimensional linearly recurring relations. Complexity analyses of all proposed methods are also provided. Furthermore, for generic polynomial systems, we present an explicit formula for the estimation of the sparsity of one main multiplication matrix, and prove that its construction is free. With the asymptotic analysis of such sparsity, we are able to show that for generic systems the complexity above becomes O(6/nπD2+n−1n)." } @book {CLO, AUTHOR = {Cox, David A. and Little, John and O'Shea, Donal}, TITLE = {Ideals, varieties, and algorithms}, SERIES = {Undergraduate Texts in Mathematics}, EDITION = {Fourth}, NOTE = {An introduction to computational algebraic geometry and commutative algebra}, PUBLISHER = {Springer, Cham}, YEAR = {2015}, PAGES = {xvi+646}, ISBN = {978-3-319-16721-3}, MRCLASS = {13P10 (13-01 14-01 14Qxx 68W30)}, MRNUMBER = {3330490}, DOI = {10.1007/978-3-319-16721-3}, URL = {https://doi.org/10.1007/978-3-319-16721-3}, } @inproceedings{Collins, title={Quantifier elimination for real closed fields by cylindrical algebraic decompostion}, author={Collins, George E}, booktitle={Automata Theory and Formal Languages 2nd GI Conference Kaiserslautern, May 20--23, 1975}, pages={134--183}, year={1975}, organization={Springer} } @inproceedings{caro2012non, title={Non-singular assembly mode changing trajectories of a 6-DOF parallel robot}, author={Caro, St{\'e}phane and Wenger, Philippe and Chablat, Damien}, booktitle={ASME 2012 International Design Engineering Technical Conferences and Computers and Information in Engineering Conference}, pages={1245--1254}, year={2012}, organization={American Society of Mechanical Engineers} } @inproceedings{FaSaSp12, title={Critical points and Gr{\"o}bner bases: the unmixed case}, author={Faug{\`e}re, Jean-Charles and {Safey El Din}, Mohab and Spaenlehauer, Pierre-Jean}, booktitle={Proceedings of the 37th International Symposium on Symbolic and Algebraic Computation}, pages={162--169}, year={2012}, organization={ACM} } @article{HaSo12, title={Algorithm 921: alphaCertified: certifying solutions to polynomial systems}, author={Hauenstein, Jonathan D and Sottile, Frank}, journal={ACM Transactions on Mathematical Software (TOMS)}, volume={38}, number={4}, pages={28}, year={2012}, publisher={ACM} } @article{HSSV18, title={Solving determinantal systems using homotopy techniques}, author={Hauenstein, Jonathan D and {Safey El Din}, Mohab and Schost, {\'E}ric and Vu, Thi Xuan}, journal={arXiv preprint arXiv:1802.10409}, year={2018} } @article{SaSc18, title={Bit complexity for multi-homogeneous polynomial system solving—Application to polynomial minimization}, author={{Safey El Din}, Mohab and Schost, {\'E}ric}, journal={Journal of Symbolic Computation}, volume={87}, pages={176--206}, year={2018}, publisher={Elsevier} } @article{Hau13, title={Numerically computing real points on algebraic sets}, author={Hauenstein, Jonathan D}, journal={Acta applicandae mathematicae}, volume={125}, number={1}, pages={105--119}, year={2013}, publisher={Springer} } @InProceedings{F5, author = {Faug\`ere, J.-C.}, title = {A new efficient algorithm for computing Gr\"obner bases without reduction to zero (F5)}, OPTcrossref = {}, OPTkey = {}, booktitle = {Proceedings of the 2002 {I}nternational {S}ymposium on {S}ymbolic and {A}lgebraic {C}omputation}, year = {2002}, OPTeditor = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, pages = {75-83}, OPTmonth = {}, OPTaddress = {}, OPTorganization = {}, OPTpublisher = {}, OPTnote = {}, OPTannote = {} } @Article{F4, author = {Faug\`ere, J.-C.}, title = {A new efficient algorithm for computing Gr\"obner bases (F4)}, journal = {Journal of Pure and Applied Algebra}, year = {1999}, OPTkey = {}, volume = {139}, number = {1-3}, pages = {61-88}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @article{SchSha, title={On the “piano movers” problem. II. General techniques for computing topological properties of real algebraic manifolds}, author={Schwartz, Jacob T and Sharir, Micha}, journal={Advances in applied Mathematics}, volume={4}, number={3}, pages={298--351}, year={1983}, publisher={Elsevier} } @Article{CoMo15, author = {Coste, M. and Moussa, S.}, title = {On the rationality of the singularity locus of a Gough-Stewart platform - biplanar case}, journal = {Mechanism and Machine Theory}, year = {2015}, OPTkey = {}, volume = {87}, OPTnumber = {}, pages = {82-92}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Book{Canny, author = {Canny, J.}, ALTeditor = {}, title = {On the complexity of robot motion planning}, publisher = {MIT Press}, year = {1988}, OPTkey = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, OPTaddress = {}, OPTedition = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{KaHu, author = {Kuffner, J.J. and Husty, M.}, title = {Classification of all self-motions of the original Stewart-Gough platform}, journal = {Computer-Aided Design}, year = {1998}, OPTkey = {}, volume = {30}, number = {3}, pages = {205-215}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @article{DaKu06, title={Bounds for gradient trajectories and geodesic diameter of real algebraic sets}, author={D'Acunto, D. and Kurdyka, K.}, journal={Bulletin of the London Mathematical Society}, volume={38}, number={6}, pages={951--965}, year={2006}, publisher={Cambridge University Press} } @Article{TII2018, author = {Reiter, A. and M{\"u}ller, A. and Gattringer, H.}, title = {On Higher-Order Inverse Kinematics Methods in Time-Optimal Trajectory Planning for Kinematically Redundant Manipulators}, journal = {IEEE Transactions on Industrial Informatics}, year = {2018}, OPTkey = {}, OPTvolume = {}, OPTnumber = {}, OPTpages = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @InProceedings{BoPl84, author = {Bock, H.G. and Plitt, K.J.}, title = {A multiple shooting algorithm for direct solution of optimal control problems}, OPTcrossref = {}, OPTkey = {}, booktitle = {Proc. of the IFAC World Congress}, year = {1984}, OPTeditor = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, pages = {242-247}, OPTmonth = {}, OPTaddress = {}, OPTorganization = {}, OPTpublisher = {}, OPTnote = {}, OPTannote = {} } @InProceedings{BoLi86, author = {Borrel, P. and Liegeois, A.}, title = {A study of multiple manipulator inverse kinematic solutions with applications to trajectory planning and workspace determination}, OPTcrossref = {}, OPTkey = {}, booktitle = {Proceedings of IEEE Conf. Rob. and Aut.}, year = {1986}, OPTeditor = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, pages = {1180-1185}, OPTmonth = {}, OPTaddress = {}, OPTorganization = {}, OPTpublisher = {}, OPTnote = {}, OPTannote = {} } @Book{angeles, author = {Angeles, J.}, ALTeditor = {}, title = {Fundamentals of Robotic Mechanical Systems, Theory, Methods, and Algorithms}, publisher = {Springer}, year = {2007}, OPTkey = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, OPTaddress = {}, OPTedition = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Book{MLS, author = {Murray, R.M. and Li, Z. and Sastry, S.S.}, ALTeditor = {}, title = {A Mathematical Introduction to Robotic Manipulation}, publisher = {CRC Press Taylor \& Francis Group}, year = {1994}, OPTkey = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, OPTaddress = {}, OPTedition = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @InProceedings{Nawratil10, author = {Nawratil, G.}, title = {Stewart Gough platforms with linear singularity surface}, OPTcrossref = {}, OPTkey = {}, booktitle = {Proc. of 19th IEEE International Workshop on Robotics in Alpe-Adria-Danube Region (RAAD'10)}, year = {2010}, OPTeditor = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, pages = {231-235}, OPTmonth = {}, OPTaddress = {}, OPTorganization = {}, OPTpublisher = {}, OPTnote = {}, OPTannote = {} } @Book{selig, author = {Selig, J.M.}, editor = {Gries, D. and Schneider, F.B.}, title = {Geometric Fundamentals of Robotics}, publisher = {Springer}, year = {2005}, OPTkey = {}, OPTvolume = {}, OPTnumber = {}, series = {Monographs in Computer Science}, OPTaddress = {}, OPTedition = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{NaSch17, author = {Nawratil, G. and Schicho, J.}, title = {Self-motions of pentapods with linear platform}, journal = {Robotica}, year = {2017}, OPTkey = {}, volume = {35}, number = {4}, pages = {832-860}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @article{SaSc17, title={A nearly optimal algorithm for deciding connectivity queries in smooth and bounded real algebraic sets}, author={{Safey El Din}, Mohab and Schost, {\'E}ric}, journal={Journal of the ACM (JACM)}, volume={63}, number={6}, pages={48}, year={2017}, publisher={ACM} } @Article{wenger, author = {Wenger, P.}, title = {Cuspidal and noncuspidal robot manipulators}, journal = {Special issue of Robotica on Geometry in Robotics and Sensing}, year = {2007}, OPTkey = {}, volume = {25}, number = {6}, pages = {677-690}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @article{SaSc11, title={A baby steps/giant steps probabilistic algorithm for computing roadmaps in smooth bounded real hypersurface}, author={{Safey El Din}, Mohab and Schost, {\'E}ric}, journal={Discrete \& Computational Geometry}, volume={45}, number={1}, pages={181--220}, year={2011}, publisher={Springer} } @Article{parenti, author = {Innocenti, C. and {Parenti-Castelli}, V.}, title = {Singularity-free evolution from one configuration to another in serial and fully-parallel manipulators, Kinematic mapping based assmbly mode evaluation of planar four-bar mechanisms}, journal = {ASME Journal of Mechanical Design}, year = {1998}, OPTkey = {}, volume = {120}, OPTnumber = {}, pages = {73-99}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{SHM, author = {Schr\"ocker, H.-P. and Husty, M. and McCarthy, J.M.}, title = {Kinematic mapping based assembly mode evaluation of planar four-bar mechanisms}, journal = {ASME Journal of Mechanical Design}, year = {2006}, OPTkey = {}, volume = {129}, OPTnumber = {9}, pages = {924-929}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{GNSS, author = {Gallet, M. and Nawratil, G. and Schicho, J. and Selig, J.M.}, title = {Mobile Icosapods}, journal = {Advances in Applied Mathematics}, year = {2017}, OPTkey = {}, volume = {88}, OPTnumber = {}, OPTpages = {}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Article{BRSS, author = {Basu, S. and Roy, M.-F. and {Safey El Din}, M. and Schost, \'E.}, title = {A Baby Step-Giant Step Roadmap Algorithm for General Algebraic Sets}, journal = {Foundations of Computational Mathematics}, year = {2014}, OPTkey = {}, volume = {14}, number = {6}, pages = {1117-1172}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Book{merlet, author = {Merlet, J.-P.}, ALTeditor = {}, title = {Parallel robots}, publisher = {Springer}, year = {2006}, OPTkey = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, OPTaddress = {}, edition = {2nd}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @Misc{irb, OPTkey = {}, author = {{IRB5500 Datasheet}}, title = {ABB Ltd, Affolternstrasse 44, 8050 Zurich, Switzerland}, howpublished = {\href{https://library.e.abb.com/public/86aad4124d6ad6dec12579f4002ab48b/DatenblattIRB5500_web.pdf}{https://library.e.abb.com/public/86aad4124d6ad6dec12579f4002ab48b/DatenblattIRB5500\\ \_web.pdf}}, OPTmonth = {}, year = {2017}, OPTnote = {}, OPTannote = {} } @Misc{ur5, OPTkey = {}, author = {{UR5 Datasheet}}, title = {Universal Robots A/S Energivej 25 DK-5260}, howpublished = {\url{http://media1.limitless.dk/UR_Tech_Spec/UR5_GB.pdf}}, OPTmonth = {}, year = {2013}, OPTnote = {}, OPTannote = {} } @Article{LaKu2, author = {LaValle, S.M. and Kuffner, J.J.}, title = {Randomized Kinodynamic Planning}, journal = {International Journal of Robotics Research}, year = {2001}, OPTkey = {}, volume = {20}, number = {5}, pages = {378-400}, OPTmonth = {}, OPTnote = {}, OPTannote = {} } @InProceedings{KuLa1, author = {Kuffner, J.J. and LaValle, S.M.}, title = {RRT-Connect: An Efficient Approach to Single-Query Path Planning}, OPTcrossref = {}, OPTkey = {}, booktitle = {IEEE International Conference on Robotics and Automation}, year = {2000}, OPTeditor = {}, OPTvolume = {}, OPTnumber = {}, OPTseries = {}, OPTpages = {}, OPTmonth = {}, OPTaddress = {}, OPTorganization = {}, OPTpublisher = {}, OPTnote = {}, OPTannote = {} } msolve-0.6.5/doc/examples/000077500000000000000000000000001456710632100154175ustar00rootroot00000000000000msolve-0.6.5/doc/examples/elim2_char1073741827.sh000077500000000000000000000001321456710632100207670ustar00rootroot00000000000000#!/bin/bash ../../msolve -e 2 -g 2 -f elim_char1073741827.ms -o elim2_char1073741827.res msolve-0.6.5/doc/examples/elim_char1073741827.ms000066400000000000000000000001121456710632100207050ustar00rootroot00000000000000t, w, x, y, z 1073741827 w^4, x^4, w*y^3+1073741826*x*z^3, t*z+1073741826 msolve-0.6.5/doc/examples/elim_char1073741827.sh000077500000000000000000000001311456710632100207040ustar00rootroot00000000000000#!/bin/bash ../../msolve -e 1 -g 2 -f elim_char1073741827.ms -o elim_char1073741827.res msolve-0.6.5/doc/examples/empty_char0.ms000066400000000000000000000000171456710632100201710ustar00rootroot00000000000000x, y 0 x*y-1, xmsolve-0.6.5/doc/examples/empty_char0.sh000077500000000000000000000000771456710632100201750ustar00rootroot00000000000000#!/bin/bash ../../msolve -f empty_char0.ms -o empty_char0.res msolve-0.6.5/doc/examples/grevlex_char1073741827.ms000066400000000000000000000001671456710632100214450ustar00rootroot00000000000000z1, z2, z3 1073741827 7*z1*z2+5*z2*z3+z3^2+z1+5*z3+10, 7*z3^2-27*z1^2-15*z2^2+59*z3+3*z1, 8*z1^2+13*z1*z3+10*z3^2+z2+z1msolve-0.6.5/doc/examples/grevlex_char1073741827.sh000077500000000000000000000001321456710632100214330ustar00rootroot00000000000000#!/bin/bash ../../msolve -g 2 -f grevlex_char1073741827.ms -o grevlex_char1073741827.res msolve-0.6.5/doc/examples/grevlex_lm_char1073741827.sh000077500000000000000000000001351456710632100221260ustar00rootroot00000000000000#!/bin/bash ../../msolve -g 1 -f grevlex_char1073741827.ms -o grevlex_lm_char1073741827.res msolve-0.6.5/doc/examples/hypersurface_char0.ms000066400000000000000000000000261456710632100215330ustar00rootroot00000000000000x, y, z 0 x^2-y^2, x-ymsolve-0.6.5/doc/examples/hypersurface_char0.sh000077500000000000000000000001151456710632100215300ustar00rootroot00000000000000#!/bin/bash ../../msolve -f hypersurface_char0.ms -o hypersurface_char0.res msolve-0.6.5/doc/examples/param_and_reals_char0.sh000077500000000000000000000001161456710632100221410ustar00rootroot00000000000000#!/bin/bash ../../msolve -P 1 -f param_char0.ms -o param_and_reals_char0.res msolve-0.6.5/doc/examples/param_char0.ms000066400000000000000000000001071456710632100201330ustar00rootroot00000000000000z1, z2, z3 0 z1^2-z2^2+z3^2-4, z1*z2+2*z2*z3-3*z3*z1-1, z1+2*z2+3*z3-1 msolve-0.6.5/doc/examples/param_char0.sh000077500000000000000000000001041456710632100201260ustar00rootroot00000000000000#!/bin/bash ../../msolve -P 2 -f param_char0.ms -o param_char0.res msolve-0.6.5/doc/examples/param_char65521.ms000066400000000000000000000001131456710632100204530ustar00rootroot00000000000000z1, z2, z3 65521 z1^2-z2^2+z3^2-4, z1*z2+2*z2*z3-3*z3*z1-1, z1+2*z2+3*z3-1 msolve-0.6.5/doc/examples/param_char65521.sh000077500000000000000000000001141456710632100204520ustar00rootroot00000000000000#!/bin/bash ../../msolve -P 2 -f param_char65521.ms -o param_char65521.res msolve-0.6.5/doc/examples/param_simple.ms000066400000000000000000000000401456710632100204230ustar00rootroot00000000000000z1, z2 0 z1^2+z2^2-1, z1^2-z2^2 msolve-0.6.5/doc/examples/param_simple.sh000077500000000000000000000001061456710632100204240ustar00rootroot00000000000000#!/bin/bash ../../msolve -P 2 -f param_simple.ms -o param_simple.res msolve-0.6.5/doc/examples/reals_dim0.ms000066400000000000000000000000651456710632100200000ustar00rootroot00000000000000x,y,z 0 x+2*y+2*z-1, x^2+2*y^2+2*z^2-x, 2*x*y+2*y*z-ymsolve-0.6.5/doc/examples/reals_dim0.sh000077500000000000000000000000751456710632100177770ustar00rootroot00000000000000#!/bin/bash ../../msolve -f reals_dim0.ms -o reals_dim0.res msolve-0.6.5/doc/examples/reals_dim0_prec256.sh000077500000000000000000000001141456710632100212370ustar00rootroot00000000000000#!/bin/bash ../../msolve -p 256 -f reals_dim0.ms -o reals_dim0_prec256.res msolve-0.6.5/doc/examples/saturate_char1073741827.ms000066400000000000000000000000721456710632100216140ustar00rootroot00000000000000w, x, y, z 1073741827 w^4, x^4, 1073741826*x*z^3+w*y^3, z msolve-0.6.5/doc/examples/saturate_char1073741827.sh000077500000000000000000000001371456710632100216140ustar00rootroot00000000000000#!/bin/bash ../../msolve -S -g 2 -f saturate_char1073741827.ms -o saturate_char1073741827.res msolve-0.6.5/doc/examples/simple_char0.ms000066400000000000000000000000651456710632100203270ustar00rootroot00000000000000x,y,z 0 x+2*y+2*z-1, x^2+2*y^2+2*z^2-x, 2*x*y+2*y*z-ymsolve-0.6.5/doc/examples/simple_char0.sh000077500000000000000000000001011456710632100203140ustar00rootroot00000000000000#!/bin/bash ../../msolve -f simple_char0.ms -o simple_char0.res msolve-0.6.5/doc/examples/simple_char65521.ms000066400000000000000000000000711456710632100206470ustar00rootroot00000000000000x,y,z 65521 x+2*y+2*z-1, x^2+2*y^2+2*z^2-x, 2*x*y+2*y*z-ymsolve-0.6.5/doc/examples/simple_char65521.sh000077500000000000000000000001111456710632100206400ustar00rootroot00000000000000#!/bin/bash ../../msolve -f simple_char65521.ms -o simple_char65521.res msolve-0.6.5/doc/macros.tex000066400000000000000000000023171456710632100156120ustar00rootroot00000000000000\def\e{{\bm{e}}} \def\s{{\bm{s}}} \def\x{{\bm{x}}} \def\y{{\bm{y}}} \def\z{{\bm{z}}} \def\X{{\bm{X}}} \def\Y{{\bm{Y}}} \def\Z{\mathbb{Z}} \def\K{\mathbb{K}} \def\N{\mathbb{N}} \def\P{\mathbb{P}} \def\Q{\mathbb{Q}} \def\R{\mathbb{R}} \def\C{\mathbb{C}} \def\A{\mathbb{A}} \def\bbF{{\mathbb{F}}} \def\F{{\bm{F}}} \def\f{{\bm{f}}} \def\g{{\bm{g}}} \def\balpha{\bm{\alpha}} \def\jac{{\mathrm{jac}}} \newcommand{\se}{\mathrm{SE}(3)} \newcommand{\confg}{\mathcal{C}} \newcommand{\pl}{\mathrm{Pl}} \newcommand{\bs}{\backslash} \def\alert#1{{\textcolor{red}{#1}}} \def\hlight#1{\textcolor{Blue}{{#1}}} \def\alert#1{\textcolor{red}{({\bf todo: #1})}} \def\anrinput#1{}%{\textcolor{red}{{#1}}} %\def\anrinput#1{\textcolor{red}{{#1}}} \def\paris#1{\textcolor{Olive}{#1}} \def\ls2n#1{\textcolor{DarkGreen}{#1}} \def\jku#1{\textcolor{magenta}{#1}} %\def\irobot#1{\textcolor{Violet}{#1}} \def\mohab#1{\textcolor{Brown}{#1}} \def\ACRONYM{\color{darkgoldenrod}{\texttt{msolve} -- A library for solving multivariate polynomial systems}} \def\msolve{{\textsc{msolve}}\xspace} \newcommand\msolveinput[1]{\begin{tcolorbox}\verbatiminput{#1}\end{tcolorbox}} %%% Local Variables: %%% mode: latex %%% TeX-master: "msolve-tutorial" %%% End: msolve-0.6.5/doc/msolve-tutorial.tex000066400000000000000000001432641456710632100175030ustar00rootroot00000000000000\documentclass[a4paper,english,11pt]{scrartcl} \usepackage{ifpdf} \ifpdf \pdfoutput=1 \fi %\usepackage[DIV=9]{typearea} \KOMAoptions{DIV=12,abstract=true} %%%%% PAQUETS % Base \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \usepackage[english]{babel} \usepackage{amsmath,amssymb,amsfonts,amsthm} \usepackage[usenames,dvipsnames,svgnames,table,hyperref]{xcolor} \usepackage{eurosym} \usepackage{listings} \lstset{ basicstyle=\tiny\ttfamily, columns=flexible, breaklines=true } % Typographies \usepackage{microtype} \usepackage{mathtools} % Pour mathrlap et compagnie \usepackage{booktabs} % De beaux tableaux \usepackage{array} \newcolumntype{R}[1]{>{\raggedleft\let\newline\\\arraybackslash\hspace{0pt}}p{#1}} \usepackage[]{csquotes} \usepackage{xspace} %\usepackage{fontawesome} % Graphiques %\usepackage{tikz} %\usepackage{tikz-cd} %\usetikzlibrary{calc,intersections,angles,quotes} \usepackage{float} \usepackage[]{graphicx} % Divers \usepackage[]{url} \usepackage[backgroundcolor=white,linecolor=red]{todonotes} \usepackage[shortlabels,inline]{enumitem} \setlist[description]{labelindent=!,labelsep=1em,font=\normalfont\bfseries} \usepackage{bm} \usepackage{libertine} % NOARXIV \usepackage[libertine,vvarbb]{newtxmath} % NOARXIV \setkomafont{sectioning}{\bfseries\rmfamily} \setkomafont{title}{} \usepackage[ruled]{caption} % La légende des boites flottantes \captionsetup{format=hang,justification=raggedright,font=small,width=.95\textwidth,labelfont=it,labelsep=period} \usepackage[titles]{tocloft} \usepackage{setspace} \setstretch{1.07} \setdisplayskipstretch{.6} % Algorithms \usepackage[]{algpseudocode} \floatstyle{ruled} \newfloat{algo}{tp}{lop} \floatname{algo}{Algorithm} \setcounter{topnumber}{1} % Pas plus d'une boite flottante en haut d'une page. \setcounter{bottomnumber}{1} % idem mais en bas % scale texttt \usepackage[scaled=.75]{beramono} % PL : Chez moi, \tt, \sf, \bf, etc ne fonctionnent pas. \def\sf{} % Il faudrait remplacer par \mathsf mais la syntaxe n'est pas la même \def\tt{\ttfamily} \definecolor{darkgoldenrod}{rgb}{0.72, 0.53, 0.04} \definecolor{amber}{rgb}{1.0, 0.75, 0.0} \definecolor{mred}{rgb}{.886,.239,.157} \definecolor{darkblue}{RGB}{63,101,134} % \usepackage[]{tocstyle} % \usetocstyle{nopagecolumn} % \settocstylefeature{pagenumberhook}{\normalfont\itshape\color{darkgoldenrod}} % \setkomafont{sectionentrypagenumber}{\itshape\color{darkgoldenrod}} \typearea{10} \setkomafont{title}{\raggedright\sffamily\bfseries\color{darkblue}} \setkomafont{title}{\raggedright\sffamily\bfseries\color{darkgoldenrod}} \addtokomafont{subtitle}{\normalfont\sffamily\raggedright\Large\itshape} \setkomafont{subject}{\raggedright\Large\sffamily\medls} \addtokomafont{author}{\raggedright\sffamily\setlength{\tabcolsep}{0pt}} \setkomafont{pageheadfoot}{\sffamily} \setkomafont{pagenumber}{\sffamily} \setkomafont{titlehead}{\sffamily} %\addtokomafont{section}{\color{darkblue}} \addtokomafont{section}{\color{darkgoldenrod}} %\addtokomafont{subsection}{\color{darkblue}} \addtokomafont{subsection}{\color{darkgoldenrod}} %\addtokomafont{subsubsection}{\normalfont\itshape\color{darkblue}} \addtokomafont{subsubsection}{\normalfont\itshape\color{darkgoldenrod}} %\addtokomafont{paragraph}{\normalfont\itshape\color{darkblue}} \addtokomafont{paragraph}{\normalfont\itshape\color{darkgoldenrod}} \ifpdf \usepackage[ linktocpage=true, hyperfootnotes=false, pdftex, % bookmarks = true,% % Signets bookmarksnumbered = true,% % Signets numerotes pdfpagemode = None,% % Signets/vignettes fermes a l'ouverture pdfstartview = FitH,% % La page prend toute la largeur pdfpagelayout = SinglePage,% Vue par page colorlinks = true,% % Liens en couleur linkcolor= red, % % couleur des liens internes citecolor =blue, urlcolor = magenta,% % Couleur des liens externes pdfborder = {0 0 0}% % Style de bordure : ici, pas de bordure ]{hyperref}% % Utilisation de HyperTeX \else \usepackage[ linktocpage=true, hyperfootnotes=false, bookmarks = true,% % Signets bookmarksnumbered = true,% % Signets numerotes pdfpagemode = None,% % Signets/vignettes fermes a l'ouverture pdfstartview = FitH,% % La page prend toute la largeur pdfpagelayout = SinglePage,% Vue par page colorlinks = true,% % Liens en couleur linkcolor= red, % % couleur des liens internes citecolor =blue, urlcolor = magenta,% % Couleur des liens externes pdfborder = {0 0 0}% % Style de bordure : ici, pas de bordure ]{hyperref}% % Utilisation de HyperTeX \fi \hypersetup{ linkcolor=blue!60!black, citecolor=red, %OrangeRed, %Emerald, %OliveGreen, urlcolor=blue, %BlueViolet %NavyBlue } \hypersetup{colorlinks=true} \usepackage{framed} %\usepackage{bm} \usepackage{cleveref} \graphicspath{{../fwf_anr_2017/etc/}} \usepackage{tcolorbox} \tcbuselibrary{skins} \usepackage{pgfgantt} \usepackage{pgfplots} \usetikzlibrary{positioning} \usetikzlibrary{fit} \usetikzlibrary{backgrounds} \usetikzlibrary{calc} %%SG\usetikzlibrary{shapes,fpu,arrows,arrows.meta,calc,matrix,shapes.geometric,decorations.pathmorphing,intersections,fit,external,backgrounds,spy} %\usetikzlibrary{mindmap} %\usetikzlibrary{decorations.text} %\tikzset{box1/.style={draw=black, thick, rectangle,rounded corners, minimum height=2cm, minimum width=2cm}} \tikzset{box1/.style={draw=black, thick, rectangle,rounded corners, fill=black!7!white}} \tikzset{box2/.style={draw=black, thick, rectangle,rounded corners, fill=black!7!white, minimum height=3cm}} \tikzset{annot/.style={draw=black,thick,rounded corners,anchor=base, fill=red!10!white}} \newtcolorbox[auto counter]{challenge}[2][]{ colframe=white!40!black,coltext=white!25!black,colback=white ,fonttitle=\bfseries, title=Exercise~\thetcbcounter} \usepackage{fancyhdr} \usepackage{verbatim} \allowdisplaybreaks[4] \newtheorem{proposition}{Proposition} \newtheorem{lemma}[proposition]{Lemma} \newtheorem{theorem}[proposition]{Theorem} \newtheorem{corollary}[proposition]{Corollary} \newtheorem{definition}[proposition]{Definition} \newtheorem{conjecture}[proposition]{Conjecture} \newtheorem*{question}{Problem} % \def\mbbone{\mathbf{1}} % ONLYARXIV \def\mbbone{\mathbb{1}} % NOARXIV \theoremstyle{definition} \newtheorem{example}[proposition]{Example} \theoremstyle{remark} %\newtheorem{example}[proposition]{Example} \newtheorem*{remark}{Remark} \newcommand{\cmment}[1]{} \newcommand{\mop}[1]{\operatorname{#1}} \newcommand{\ud}{\mathrm{d}} \newcommand{\st}{\ \middle|\ } %\newcommand{\eqdef}{\smash{\ \stackrel{\text{def}}{=}\ }} \newcommand{\eqdef}{\triangleq} \newcommand{\abs}[1]{\left|#1\right|} \newcommand{\bA}{{\mathbb{A}}} \newcommand{\bE}{{\mathbb{E}}} \newcommand{\bP}{{\mathbb{P}}} \newcommand{\bN}{{\mathbb{N}}} \newcommand{\bC}{{\mathbb{C}}} \newcommand{\bQ}{{\mathbb{Q}}} \newcommand{\bR}{{\mathbb{R}}} \newcommand{\bF}{{\mathbb{F}}} \newcommand{\bK}{{\mathbb{K}}} \newcommand{\bS}{{\mathbb{S}}} \newcommand{\bZ}{{\mathbb{Z}}} \newcommand{\cL}{{\mathcal{L}}} \newcommand{\cB}{{\mathcal{B}}} \newcommand{\cD}{{\mathcal{D}}} \newcommand{\cY}{{\mathcal{Y}}} \newcommand{\cT}{{\mathcal{T}}} \newcommand{\cS}{{\mathcal{S}}} \newcommand{\cN}{{\mathcal{N}}} \newcommand{\cO}{{\mathcal{O}}} \newcommand{\cH}{{\mathcal{H}}} \newcommand{\cU}{{\mathcal{U}}} \newcommand{\vol}{\mop{vol}} \newcommand{\Sqrt}{\mop{Sqrt}} \newcommand{\Sin}{\mop{Sin}} \newcommand{\Cos}{\mop{Cos}} \newcommand{\NJ}{\mop{NJ}} \newcommand{\Proj}{\ensuremath{\bP^n}} \newcommand{\intx}[1]{\int_{\mathrlap{#1}}} \newcommand{\muav}{\mu_{\textrm{av}}} \newcommand\Fquatre{\textsc{\texorpdfstring{F\textsubscript{4}}{F4}}\xspace} \def\geq{\geqslant} \def\leq{\leqslant} \makeatletter \def\cqlt{c.ql.t\@ifnextchar{.}{}{.\xspace}} %\bf and KOMA do not work in jcapco TeX distribution it complains that \bf is an old command if KOMA is active \DeclareOldFontCommand{\rm}{\normalfont\rmfamily}{\mathrm} \DeclareOldFontCommand{\sf}{\normalfont\sffamily}{\mathsf} \DeclareOldFontCommand{\tt}{\normalfont\ttfamily}{\mathtt} \DeclareOldFontCommand{\bf}{\normalfont\bfseries}{\mathbf} \DeclareOldFontCommand{\it}{\normalfont\itshape}{\mathit} \DeclareOldFontCommand{\sl}{\normalfont\slshape}{\@nomath\sl} \DeclareOldFontCommand{\sc}{\normalfont\scshape}{\@nomath\sc} \makeatother %\usepackage[pdftex,hypertexnames=false,hidelinks]{hyperref} \input{macros.tex} % \newtheorem{pbm}{Problem} % \newtheorem{definition}{Definition} % \newtheorem{theorem}[definition]{Theorem} % \newtheorem{corollary}[definition]{Corollary} % \newtheorem{proposition}[definition]{Proposition} % \newtheorem{lemma}[definition]{Lemma} % \newtheorem{remark}[definition]{Remark} \titlehead{\ACRONYM} \title{How to solve multivariate polynomial systems with {\msolve}?} \date{} \usepackage[ % citestyle=authoryear, bibstyle=authoryear, citestyle=numeric, bibstyle=numeric, % dashed=false, backend=biber, isbn=false, doi=false,url=false, maxcitenames=50, hyperref=true, maxbibnames=20, firstinits=true ]{biblatex} \bibliography{biblio} \usepackage{mathrsfs} \begin{document} \maketitle \tableofcontents \section{Introduction} \msolve~is a C library for solving multivariate polynomial systems of equations. It relies on computer algebra, a.k.a.\ symbolic computation, algorithms to compute \emph{algebraic} representations of the solution set from which many, if not all, informations can be extracted. Solving polynomial systems with \msolve~is \emph{global} by contrast to \emph{local} numerical routines. The use of computer algebra methods allow also the user to bypass classical numerical issues encountered by numerical methods for polynomial system solving such as those based on numerical homotopy continuation or semi-definite programming. \msolve~relies mainly on Gr\"obner bases algorithms (see below for a some basic definitions and properties). It is highly optimized, uses \texttt{AVX2} vectorization instructions and multi-threading. It uses the \href{https://gmplib.org/}{\texttt{GMP}} library (handling multi-precision integers) and the \href{https://flintlib.org/}{\texttt{FLINT}} library (handling arithmetics of univariate polynomials). \msolve~can be downloaded from \begin{center} \url{https://msolve.lip6.fr} \end{center} where binaries (for \texttt{x86} processors runing Linux operating systems) and source files are provided. \msolve~is designed for $64$ bit architectures, with \texttt{AVX2} instructions. \msolve allows you to: \begin{itemize} \item isolate all real solutions to polynomial systems with rational coefficients and finitely many complex solutions; \item compute Gr\"obner bases of polynomial systems with coefficients which are either rational numbers or in a prime field $\mathbb{Z}/p\mathbb{Z}$ with $p < 2^{31}$; \item compute parametrizations of the solutions of polynomial systems with coefficients which are either rational numbers or in a prime field $\mathbb{Z}/p\mathbb{Z}$ with $p < 2^{31}$ (assuming that the system has finitely many solutions with coordinates in an algebraic closure of the field generated by the input coefficients). \end{itemize} \msolve is based on Gr\"obner bases computations. When launching \msolve on an input polynomial system (see the file format in~\cref{sec:input}), a Gr\"obner basis computation starts and allows \msolve to determine if the number of solutions to the system is infinite or finite in an algebraic closure of the base field (the complex numbers when the input coefficients are rational numbers). When the number of solutions is finite, one says that the system (or the ideal generated by the input equations) has dimension zero at most. Else it has positive dimension. \Cref{sec:dim} shows how \msolve behaves when the input system has positive dimension or when there is no solution at all in an algebraic closure of the base field (over the complex numbers when the input coefficients are rational numbers). When the system has dimension at most zero, \msolve can compute the real solutions or, as said above, compute a Gr\"obner basis (when the base field is a prime field) or compute a parametrization of the solutions. \Cref{sec:solvingreals} shows how to use \msolve for solving polynomial systems over the reals when they have dimension at most zero. \Cref{sec:grobner} shows how to use \msolve for computing Gr\"obner bases over prime fields (with some restriction on the bit size of the considered prime). \Cref{sec:param} shows how to use \msolve for computing rational parametrizations of solutions to polynomial systems which have dimension at most zero. Finally, \cref{sec:flags} summarizes some options which can be used rational parametrizations of solutions to polynomial systems which have dimension at most zero. Finally, \cref{sec:flags} summarizes some options which can be used. The \msolve library is described in \cite{msolve} with implementation details on the algorithms used therein. All computations performed over the rational numbers (e.g. for computing real roots) are based on multi-modular computations with a probabilistic stopping criterion. Unless explicitely requested by the user (see the \verb+-l+ flag in \cref{sec:flags}), all computations of Gr\"obner bases in prime fields use deterministic algorithms. Change of order algorithms which are used are deterministic when the input ideal is radical. \section{Input file format}\label{sec:input} \msolve allows you to solve polynomial systems either with coefficients which are either rational numbers or in a prime field $\mathbb{Z}/p\mathbb{Z}$ with $p < 2^{31}$. If you aim at solving polynomial systems with coefficients which are floating point numbers, you can just replace these floating point numbers with rational numbers. Further, we explain how the input files of \msolve should be. Consider the following polynomial system of equations \[ \begin{array}{rcl} x+2 y+2 z-1 &= &0\\ x^2+2 y^2+2 z^2-x &= &0\\ 2 x y+2 y z-y &= &0 \end{array} \] in $\Q[x,y,z]$. In order to solve it with \msolve~one simply produces a file with the following content \msolveinput{examples/simple_char0.ms} Hence the structure of input files to \msolve is as follows: \begin{enumerate} \item the first line contains the variables of the input system, separated with a comma; \item the second line contains the characteristic of the field over which computations are performed; \item the next lines contain polynomials, in expanded form, separated by a comma (except the last one) and with a line break. \end{enumerate} When one wants to solve this system over $\frac{\Z}{65521\Z}$ one just replaces $0$ by $65521$ in the second line. Note that in the positive characteristic case the coefficients used should be smaller or equal to $2^{31}-1$. \msolveinput{examples/simple_char65521.ms} \section{Computing the dimension}\label{sec:dim} To make things explicit on the behaviour of \msolve when the input system does not have finitely many complex solutions, let us consider first the example below. \msolveinput{examples/empty_char0.ms} Then, \msolve outputs \begin{tcolorbox} % examples/empty_char0.res \begin{lstlisting}[basicstyle=\normalsize\ttfamily] [-1]: \end{lstlisting} \end{tcolorbox} indicating that the dimension of the set of complex solutions is $-1$, hence it is empty. If now, one considers the following example. \msolveinput{examples/hypersurface_char0.ms} Then, \msolve outputs \begin{tcolorbox} % examples/hypersurface_char0.res \begin{lstlisting}[basicstyle=\normalsize\ttfamily] [1, 3, -1, []]: \end{lstlisting} \end{tcolorbox} The first integer $1$ indicates that the complex solution is positive dimensional (note that the actual dimension of the complex solution set is $2$). \section{Solving over the reals (finitely many solutions)}\label{sec:solvingreals} The basic functionality \msolve allows you to perform is real root isolation for polynomial systems with rational coefficients and {\em with finitely many complex solutions}. This latter requirement is automatically tested by \msolve. For instance, consider the following input to \msolve written in a file \verb+in.ms+. \msolveinput{examples/reals_dim0.ms} Then, typing the following command line \begin{tcolorbox} % examples/reals_dim0.sh \begin{verbatim} ./msolve -f in.ms -o out.ms \end{verbatim} \end{tcolorbox} will display in the \verb+out.ms+ file the following content. \begin{tcolorbox} % examples/reals_dim0.res \begin{lstlisting} [0, [1, [[[107291359935630315248585097660753910587 / 2^127, 26822839983907578812146274415188477647 / 2^125], [107291359935630315248585097660753910587 / 2^128, 26822839983907578812146274415188477647 / 2^126], [-355532291286331190123863132844989723573 / 2^131, -1422129165145324760495452531379958894291 / 2^133]], [[1, 1], [0, 0], [0, 0]], [[38543940173343311950004019810003894311 / 2^127, 77087880346686623900008039620007788667 / 2^128], [9635985043335827987501004952500973579 / 2^126, 4817992521667913993750502476250486791 / 2^125], [93053303113782607831679264095876317083 / 2^128, 372213212455130431326717056383505268333 / 2^130]], [[7089215977519551322153637654828504405 / 2^124, 113427455640312821154458202477256070491 / 2^128], [-1 / 2^127, 1 / 2^127], [1814839290245005138471331239636097127765 / 2^132, 907419645122502569235665619818048563883 / 2^131]]] ]]: \end{lstlisting} \end{tcolorbox} This is a list whose first element is the integer $0$ indicating that the input polynomial system has finitely many complex solutions. The second element of this list is a list which provides the coordinates of the real solutions as follows: \begin{itemize} \item the first element is an integer $\ell$ indicating how many lists are given further; in the above example, the integer $1$ tells that we have a single list (this will be the usual case); \item the next are $\ell$ lists $L_1, \ldots, L_\ell$ which encode the solutions to the input system; each of them containing boxes isolating a single real solution. \end{itemize} For instance, from the above output, we deduce that the box defined by \[ \left \{ \begin{array}{l} \frac{107291359935630315248585097660753910587}{2^{127}} \leq x \leq \frac{26822839983907578812146274415188477647}{2^{125}}, \\ \frac{107291359935630315248585097660753910587}{2^{128}} \leq y \leq \frac{26822839983907578812146274415188477647}{2^{126}}, \\ \frac{-355532291286331190123863132844989723573}{2^{131}} \leq z \leq \frac{-1422129165145324760495452531379958894291}{2^{133}} \end{array}\right . \] contains a single real solution to the input system. Sometimes, it makes sense to increase the precision. To do that, we use the \verb+-p+ flag, followed by an integer monitoring the used precision, as follows. \begin{tcolorbox} % examples/reals_dim0_prec256.sh \begin{verbatim} ./msolve -p 256 -f in.ms -o out.ms \end{verbatim} \end{tcolorbox} We obtain in \verb+out.ms+ the following \begin{tcolorbox} % examples/reals_dim0_prec256.res \begin{lstlisting} [0, [1, [[[36509357909062631536129668436573070012487487067100583303001175658946635606055 / 2^255, 4563669738632828942016208554571633751560935883387572912875146957368329450757 / 2^252], [36509357909062631536129668436573070012487487067100583303001175658946635606055 / 2^256, 4563669738632828942016208554571633751560935883387572912875146957368329450757 / 2^253], [-60490684797868661441895377475208744393359927205523538345094237255746825568573 / 2^258, -483925478382949291535163019801669955146879417644188306760753898045974604548583 / 2^261]], [[1, 1], [0, 0], [0, 0]], [[3278955798161077339921616998930436909728483733114914607048732943254033559905 / 2^253, 26231646385288618719372935991443495277827869864919316856389863546032268479285 / 2^256], [6557911596322154679843233997860873819456967466229829214097465886508067119813 / 2^255, 13115823192644309359686467995721747638913934932459658428194931773016134239637 / 2^256], [63328796466738957984825113025800917297614244935801930326677856915848592681411 / 2^257, 126657592933477915969650226051601834595228489871603860653355713831697185362823 / 2^258]], [[2412335192444087404657728854347664746943124680534178417488699666831523534165 / 2^252, 38597363079105398474523661669562635951089994888546854679819194669304376546651 / 2^256], [-1 / 2^255, 1 / 2^255], [617557809265686375592378586713002175217439918216749674877107114708870024746325 / 2^260, 308778904632843187796189293356501087608719959108374837438553557354435012373163 / 2^259]]] ]]: \end{lstlisting} \end{tcolorbox} \section{Computing Gr\"obner bases}\label{sec:grobner} \msolve relies on Gr\"obner bases algorithms which allow one to rewrite the input polynomial system as an equivalent system which reveals properties of the solution set (dimension, degree) and to compute ``modulo'' the input equations. \msolve provides Gr\"obner bases computations for the so-called \emph{grevlex} ordering (see e.g.~\cite{CLO}) when the coefficients either lie in the field of rational numbers or when they lie in the prime field case. For instance, assume the file \verb+in.ms+ contains the following: \msolveinput{examples/grevlex_char1073741827.ms} Now, typing the following command: \begin{tcolorbox} % examples/grevlex_char1073741827.sh \begin{verbatim} ./msolve -g 2 -f in.ms -o out.ms \end{verbatim} \end{tcolorbox} where the \verb+-g+ flag indicates that one aims at computing a Gr\"obner basis. The value \verb+2+ tells \msolve to compute the Gr\"obner basis for the \emph{grevlex order} with $z_1\succ z_2 \succ z_3 $. The computed Gr\"obner basis is then printed in the file \verb+out.ms+ as follows. \begin{tcolorbox} % examples/grevlex_char1073741827.res \begin{lstlisting} #Reduced Groebner basis data #--- #field characteristic: 1073741827 #variable order: z1, z2, z3 #monomial order: graded reverse lexicographical #length of basis: 6 elements sorted by increasing leading monomials #--- [1*z2^2+832149913*z1^1*z3^1+876889156*z3^2+295279002*z1^1+724775733*z2^1+143165573*z3^1, 1*z1^1*z2^1+613566759*z2^1*z3^1+766958448*z3^2+766958448*z1^1+613566759*z3^1+153391691, 1*z1^2+134217730*z1^1*z3^1+268435458*z3^2+671088642*z1^1+671088642*z2^1, 1*z2^1*z3^2+722232944*z3^3+180778379*z1^1*z3^1+1027531442*z2^1*z3^1+173735741*z3^2+936498976*z1^1+702034498*z2^1+921316952*z3^1+59915395, 1*z1^1*z3^2+557357968*z3^3+911535897*z1^1*z3^1+419648179*z2^1*z3^1+96648475*z3^2+698659259*z1^1+282295066*z2^1+885328953*z3^1+769127629, 1*z3^4+250491376*z3^3+716275774*z1^1*z3^1+91652836*z2^1*z3^1+88303466*z3^2+855797860*z1^1+18642214*z2^1+728901227*z3^1+969918485]: \end{lstlisting} \end{tcolorbox} When one is interested only in the leading monomials of the Gr\"obner basis (which is a way smaller output), one simply uses the \verb+-g 1+ flag as follows \begin{tcolorbox} % examples/grevlex_lm_char1073741827.sh \begin{verbatim} ./msolve -g 1 -f in.ms -o out.ms \end{verbatim} \end{tcolorbox} and we obtain: \begin{tcolorbox} % examples/grevlex_lm_char1073741827.res \begin{lstlisting} #Leading ideal data #--- #field characteristic: 1073741827 #variable order: z1, z2, z3 #monomial order: graded reverse lexicographical #length of basis: 6 elements sorted by increasing leading monomials #--- [z2^2, z1^1*z2^1, z1^2, z2^1*z3^2, z1^1*z3^2, z3^4]: \end{lstlisting} \end{tcolorbox} Note that from this list of monomials, one can deduce the Hilbert series of the ideal generated by the input equations and then its dimension and its degree (see~\cite{CLO}). For instance, in the above example, one can deduce that the ideal has dimension $0$ (finitely many solutions with coordinates in an algebraic closure of $\frac{\mathbb{Z}}{1073741827\mathbb{Z}}$) since the basis of leading monomials contain pure powers of all variables. The degree of the ideal is also $8$ since there are $8$ monomials in $z_1, z_2, z_3$ which are not divisible by the above leading monomials. \msolve also allows you to perform Gröbner bases computations using \emph{one-block elimination monomial order} thanks to the \verb+-e+ flag. The following command \begin{tcolorbox} % examples/elim_char1073741827.sh \begin{verbatim} ./msolve -e 1 -g 2 -f in.ms -o out.ms \end{verbatim} \end{tcolorbox} on \msolveinput{examples/elim_char1073741827.ms} will perform the Gröbner basis computation eliminating the first variable. The output is \begin{tcolorbox} \begin{lstlisting} #Reduced Groebner basis data #--- #field characteristic: 1073741827 #variable order: t, w, x, y, z #monomial order: eliminating first variable, blocks: graded reverse lexicographical #length of basis: 7 elements sorted by increasing leading monomials #--- [1*w^1*y^3+1073741826*x^1*z^3, 1*x^4, 1*w^1*x^3, 1*w^2*x^2, 1*w^3*x^1, 1*w^4, 1*t^1*z^1+1073741826]: \end{lstlisting} \end{tcolorbox} where we see that the first $6$ polynomials are only in $w,x,y,z$, which corresponds to the elimination of the variable $t$. When the input coefficients lie in the field of rational numbers (hence, characteristic $0$), the returned Gröbner basis is the one of the {\em elimination ideal}, i.e. they have partial degree $0$ in the variables to eliminate. More generally, using \verb+-e k+ will eliminate the $k$ first variables. Thus \begin{tcolorbox} % examples/elim2_char1073741827.sh \begin{verbatim} ./msolve -e 2 -g 2 -f in.ms -o out.ms \end{verbatim} \end{tcolorbox} will eliminate $t$ and $w$, yielding \begin{tcolorbox} % examples/elim2_char1073741827.res \begin{lstlisting} #Reduced Groebner basis data #--- #field characteristic: 1073741827 #variable order: t, w, x, y, z #monomial order: eliminating first 2 variables, blocks: graded reverse lexicographical #length of basis: 7 elements sorted by increasing leading monomials #--- [1*x^4, 1*w^1*y^3+1073741826*x^1*z^3, 1*w^1*x^3, 1*t^1*z^1+1073741826, 1*w^2*x^2, 1*w^3*x^1, 1*w^4]: #Reduced Groebner basis for input in characteristic 1073741827 #for variable order t, w, x, y, z #w.r.t. grevlex monomial ordering #consisting of 7 elements: [1*x^4, 1*w^1*y^3+1073741826*x^1*z^3, 1*w^1*x^3, 1*t^1*z^1+1073741826, 1*w^2*x^2, 1*w^3*x^1, 1*w^4]: \end{lstlisting} \end{tcolorbox} where we see that only the first polynomial is not in $t$ and $w$. \section{Parametrizations of (finitely many) solutions} \label{sec:param} Assume that the input polynomials have coefficients in some field $\K$ with variables $x_1, \ldots, x_n$. In the case of polynomial systems of dimension $0$, \msolve computes by default a zero-dimensional parametrization of the solution set. The user can obtain such an encoding using the \verb+-P+ flag (see below). Let us recall what a rational parametrization is. This is a couple $(\mathscr{P}, \ell)$ where $\ell$ is a linear form $\lambda_1 x_1 + \cdots + \lambda_n x_n$ with $\lambda_i\in \K$ (for $1\leq i \leq n$), $\mathscr{P}$ is a sequence of polynomials $(w, w', v_1, \ldots, v_n)$ in $\K[t]$ where $t$ is a new variable such that: \begin{itemize} \item when $\K$ is a prime field, $w'=1$ else $w' = \frac{\partial w}{\partial t}$; \item $\deg(v_i) < \deg(w)$ for $1\leq i \leq n$; \item $\lambda_1 v_1 +\cdots +\lambda_n v_n = tw' \mod w$ \end{itemize} and the solution set to the input polynomials coincides with the set: \[ \left \{\left (-\frac{v_1(\vartheta)}{w'(\vartheta)}, \ldots, -\frac{v_n(\vartheta)}{w'(\vartheta)}\right ) \st w(\vartheta) = 0 \right\}. \] In algebraic words, the polynomials \(w' x_i + v_i\) belong to the radical of the ideal generated by the input equations and the form \(\lambda_1 x_1 + \cdots + \lambda_n x_n + t\). \msolve outputs univariate polynomials as an array \verb+[deg,L]+ where \verb+deg+ is the degree of the polynomial under consideration and \verb+L+ is the array of its coefficients in the monomial basis by increasing degree and \verb+c+ is a denominator to all coefficients. For instance, the polynomial \(x^2+3x-2\) is encoded by \begin{verbatim} [2, [-2, 3, 1]] \end{verbatim} We first explain \msolve's output in the case where the input coefficients are rational numbers (the characteristic zero case). For an input in the file \verb+in.ms+ \msolveinput{examples/param_simple.ms} the command \begin{tcolorbox} % examples/param_simple.sh \begin{verbatim} ./msolve -P 2 -f in.ms \end{verbatim} \end{tcolorbox} \msolve outputs is \begin{tcolorbox} % examples/param_simple.res \begin{lstlisting} [0, [0, 3, 4, ['z1', 'z2', 'A'], [-119/576,69/576,5/576], [1, [[4, [883600, 0, -18922, 0, 25]], [3, [0, -37844, 0, 100]], [ [[3, [223720, 0, -1190, 0]], 1], [[3, [129720, 0, 690, 0]], 1] ]]]]]: \end{lstlisting} \end{tcolorbox} and has the following structure \begin{tcolorbox} \begin{lstlisting} [0, [0, nvars, deg, vars, form, [1,[lw, lwp, param]]]]: \end{lstlisting} \end{tcolorbox} where \begin{itemize} \item the first $0$ indicates that the input system has finitely many complex solutions (dimension at most $0$); \item the second $0$ is the characteristic; \item \verb+nvars+ is the number of variables used for the parametrization (it coincides with the number of input variables if the form $\ell$ is chosen as one of the variables else it is one more); \item \verb+deg+ is the number of solutions, \emph{counted with multiplicities} (in other words the degree of the ideal generated by the input equations); \item \verb+vars+ is the list of variables following the ordering used for computing the parametrization (hence, with maybe with one more variable than the ones given as input). In our example, \msolve outputs: \begin{verbatim} ['z1', 'z2', 'A'] \end{verbatim} where \verb+A+ is a new variable. \item \texttt{form} is the list of coefficients for the linear form $\ell$ when it does not coincide with one of the input variables (else it is an empty list); In our example, this is a list of three rational numbers, say \verb+[-119/576,69/576,5/576]+, indicating that the linear form used to compute the rational parametrization is \begin{verbatim} -119/576*z1+69/576*z2+5/576*A \end{verbatim} \item the next $1$ indicates that a single parametrization is returned next (the one encoded by \verb+[lw, lwp, param]+); \item \verb+lw+ is the encoding of the eliminating polynomial $w$; \item \verb+lwp+ is the encoding of the denominator used in the rational parametrization; \item \verb+param+ is the list of the output parametrizations, there are $n-1$ where $n$ is the number of elements in \verb+vars+ ; they are encoded as follows \verb+[[deg, L], c]+ where \verb+c+ is an integer which divides the polynomial encoded by \verb+[deg, L]+. The first one corresponds to the first variable in \verb+vars+, the second parametrization corresponds to the second variable in \verb+vars+ and so on. Hence, the variable which is used to parametrize the solution set is always the last one. \end{itemize} We illustrate now how the output looks like on input file \verb+in.ms+ \msolveinput{examples/param_char0.ms} Using \verb+./msolve -P 2 -f in.ms+ the output is \begin{tcolorbox} % examples/param_char0.res \begin{lstlisting} [0, [0, 3, 4, ['z1', 'z2', 'z3'], [0, 0, 1], [1, [[4, [-116, -210, 1484, -344, 53]], [3, [-210, 2968, -1032, 212]], [ [[3, [1894, 162, -1636, 192]], 1], [[3, [-146, -620, -3118, 314]], 1] ]]]]]: \end{lstlisting} \end{tcolorbox} On this example, all variables are parametrized by the variable \verb+z3+. The polynomial $w$ is $-116 - 210 z_3 + 1484 z_3^2 -344 z_3^3 + 53 z_3^4$. The polynomials $v_1$ and $v_2$ are respectively \[ v_1 = 1894 + 162 z_3 - 1636 z_3^2 + 192 z_3^3 \quad \text{ and } \quad v_2 = -146 -620 z_3 - 3118 z_3^2 + 314 z_3^3. \] Note that we can get both the parametrization and the real roots. For instance, using the command \verb+./msolve -P 1 -f in.ms+, one obtains \begin{tcolorbox} % example/param_and__reals_char0.res \begin{lstlisting} [0, [0, 3, 4, ['z1', 'z2', 'z3'], [0, 0, 1], [1, [[4, [-116, -210, 1484, -344, 53]], [3, [-210, 2968, -1032, 212]], [ [[3, [1894, 162, -1636, 192]], 1], [[3, [-146, -620, -3118, 314]], 1] ]]]],[1, [[[679375673646273705027530285330331715009 / 2^128, 339687836823136852513765142665165857505 / 2^127], [-60535166785954698124918883091179878673 / 2^128, -3783447924122168632807430193198742417 / 2^124], [-1162789190151604508343028862486419979779 / 2^132, -581394595075802254171514431243209989889 / 2^131]], [[-756665306660103909967296571629791504137 / 2^128, -756665306660103909967296571629791504135 / 2^128], [88745898258177294078528671940999802399 / 2^126, 177491796516354588157057343881999604799 / 2^127], [2063895933416661444279689618845660247455 / 2^132, 4127791866833322888559379237691320494911 / 2^133]]] ]]: \end{lstlisting} \end{tcolorbox} We end this section with the same example as above but seeing the coefficients in \(\Z/65521\Z\). \msolveinput{examples/param_char65521.ms} The call \verb+./msolve -P 2 -f in.ms+ then outputs \begin{tcolorbox} % examples/param_char65521.res \begin{lstlisting} [0, [65521, 3, 4, ['z1', 'z2', 'z3'], [0, 0, 1], [1, [[4, [16069, 9886, 28, 2466, 1]], [0, [1]], [ [[3, [6276, 37054, 57744, 4959]]], [[3, [29622, 14235, 36649, 30281]]] ]]]]]: \end{lstlisting} \end{tcolorbox} \section{Saturation and colon ideals}\label{sec:f4sat} \msolve also proposes algorithms for computing Gr\"obner bases of saturation and colon ideals. Given $m+1$ polynomials $f_1,\ldots,f_m,\varphi$ over a field $\K$ with variables $x_1,\ldots,x_n$, the saturation ideal $\langle f_1,\ldots,f_m\rangle:\langle \varphi\rangle^{\infty}$ is the ideal of all polynomials $h$, such that there exists $k\in\N$ such that $h \varphi^k\in\langle f_1,\ldots,f_m\rangle$. The colon ideal $\langle f_1,\ldots,f_m\rangle:\langle \varphi\rangle$ is the ideal of all polynomials $h$, such that $h \varphi\in\langle f_1,\ldots,f_m\rangle$. A Gr\"obner basis for the \emph{grevlex order} can be computed in the former case with an input file containg $f_1,\ldots,f_m,\varphi$ and called with the flag \verb+-S+ to use the F4SAT algorithm. For instance, consider the following input to \msolve written in a file \verb+in.ms+. \msolveinput{examples/saturate_char1073741827.ms} Then, typing the following command line \begin{tcolorbox} % examples/saturate_char1073741827.sh \begin{verbatim} ./msolve -S -g 2 -f in.ms -o out.ms \end{verbatim} \end{tcolorbox} will display in the \verb+out.ms+ file the following content. \begin{tcolorbox} \begin{lstlisting} #Reduced Groebner basis data #--- #field characteristic: 1073741827 #variable order: w, x, y, z #monomial order: graded reverse lexicographical #length of basis: 6 elements sorted by increasing leading monomials #--- [1*w^1*y^3+1073741826*x^1*z^3, 1*x^4, 1*w^1*x^3, 1*w^2*x^2, 1*w^3*x^1, 1*w^4]: \end{lstlisting} \end{tcolorbox} % \section{Preliminaries} % Polynomial systems arise in a wide range of applications in engineering and % computing sciences. What it means to ``solve'' a polynomial system mainly % depends on the application, the \emph{domain} where the coefficients lie and the % properties of the solution set. % For instance, in many applications of engineering sciences, the coefficients lie % in the \emph{field} of rational numbers $\Q$. Sometimes, these coefficients % appear as \emph{floating point} numbers but since floating point arithmetics is % not fully convenient to handle reliably non-linear systems, the end-user may % coerce these coefficients into rational numbers. There, using continued % fractions is quite useful as it allows one to obtain reliable approximations % with integers of small \emph{height} (hence small length when represented with % bits). % All in all, one ends up with polynomial equations in the polynomial ring % $\Q[x_1, \ldots, x_n]$, i.e. the set of polynomials with coefficients in $\Q$ % and involving indeterminates $x_1, \ldots, x_n$. % In such applications, the end-user will most of the time expect informations on % the solutions with coordinates in the field of real numbers $\R$ (for instance % in robotics or biology) or in the field of complex numbers $\C$ (for instance in % signal theory). % When the number of solutions of such systems in $\C^n$ is finite (one says that % such systems have dimension at most zero), then it is well-known that the % coordinates of the solutions can be parametrized by an \emph{algebraic number} % at which one evaluates a rational fraction. In other words, there exist % univariate polynomials $(w, v_1, \ldots, v_n)$ in $\Q[t]$ such that $w$ is % square-free and the solution set in $\C^n$ can be written as % \[ % \left \{ % \left (\frac{v_1(\vartheta)}{w'(\vartheta)}, \ldots, % \frac{v_n(\vartheta)}{w'(\vartheta)}\right ) \quad \st \quad w(\vartheta) = 0 % \right \} % \] % where % $w'=\frac{\ud w}{\ud t}$. % % $w'=\frac{\partial w}{\partial t}$. % Note that, with such an encoding % (which is called a rational parametrization of the solution set), one can % approximate at arbitrary precision the solutions of the input system (by isolating % the ones of the univariate polynomial $w$). % Note also that, since $w$ is square-free, $w$ and $w'$ are co-prime and the % denominator in the above parametrization can be replaced by a constant. % Remark that the total number of solutions in $\C^n$ equals the degree of $w$. % Hence, when the input system has no complex solution, $w$ is a non-zero % constant. Also, the number of real roots to the input system is the number of % real roots of $w$. % Note also that this encoding loses the number of solutions counted with % \emph{multiplicities} ; this number is called the \emph{degree} of the input % system (which always dominates the number of complex solutions). % For systems in $\Q[x_1, \ldots, x_n]$, \msolve~is able to decide if they have % finitely many complex solutions and, in that case, returns a rational % parametrization of the solution set in $\C^n$. It also counts and isolates the % real roots of the polynomial $w$. We refer to Section~\ref{sec:zerodim} for % details on how \msolve~encodes such outputs. % When the input system has infinitely many complex solutions, \msolve~can output % a \emph{Gr\"obner basis} of the \emph{ideal} generated by all input polynomials % ; this is a family of polynomials which is obtained by taking appropriate % algebraic combinations of the input polynomials and from which one can extract % several properties of the solution set, in particular its \emph{dimension} and % its \emph{degree} (see Section~\ref{sec:posdim}). % For applications in cryptology and/or coding theory, polynomial systems lie in % some polynomial ring $\bF[x_1, \ldots, x_n]$ where $\bF$ is some finite field. In % that situation, \msolve~only supports prime field $\frac{\Z}{p\Z}$ with $p < % 2^{31}$. Denoting by $\overline{\bF}$ an algebraic closure of $\bF$, such systems % have dimension at most $0$ when they have finitely many solutions in % $\overline{\bF}^n$, else they have positive dimension. For systems of dimension % at most zero, a rational parametrization as above can be computed when the % characteristic of the field is large enough. % \section{Solving polynomial systems of dimension at most zero}\label{sec:zerodim} % Let $\K$ be a field and $\overline{\K}$ be an algebraic closure of $\K$. We % consider polynomials $(f_1, \ldots, f_s)$ in $\K[x_1, \ldots, % x_n]$ and $V$ be the set of solutions to the system % \[ % f_1=\cdots=f_s=0 % \] % in $\overline{\K}^n$. % When $V$ is % empty, % % in $\overline{\K}[x_1, \ldots, x_n]$, % the % output of \msolve~is % \begin{verbatim} % [1, []] % \end{verbatim} % When $V$ is finite, say $V$ is the union of the $\ell$ points $\balpha_1, % \ldots, \balpha_\ell$ in $\overline{\K}^n$ with $\balpha_i = (\alpha_{i,1}, % \ldots, \alpha_{i,n})$, % % When the input system has finitely many solutions in % % $\overline{\K}^n$, % the % output is encoded as follows: % % \begin{verbatim} % % [dim, [deg, nbsols, form, vars, [lw, lwp, param]]] % % \end{verbatim} % % where % % \begin{itemize} % % \item \texttt{dim} is $0$ (which indicates that the input system has finitely % % many solutions); % % \item \texttt{deg} is the number of solutions counted with multiplicities in % % $\overline{\K}^n$; % % \item \texttt{nbsols} is the number of solutions in $\overline{\K}^n$; % % \item \texttt{form} is the linear form $t$; % % \item \texttt{vars} is the list of the variables which are parametrized; % % \item \texttt{lw} is the encoding of the eliminating polynomial $w$; % % \item \texttt{lwp} is the encoding of the denominator used in the rational % % parametrization; % % \item \texttt{param} is the list of the output parametrizations as described % % above ; the $i$th one corresponds to the $i$th element of \texttt{vars}. % % % \textcolor{magenta}{I am not sure this is still the case, maybe I used a reverse % % % ordering.} % % \end{itemize} % \begin{verbatim} % [dim, nbvar, deg, varstr, linform, lw, lwp, param] % \end{verbatim} % in characteristic $0$, where % \begin{itemize} % \item \texttt{dim} is $0$ (which indicates that the input system has finitely % many solutions); % \item \texttt{nbvar} is the number of variables; % \item \texttt{deg} is the number of solutions counted with multiplicities in % $\overline{\K}^n$; % % \item \texttt{nbsols} is the number of solutions in $\overline{\K}^n$; % \item \texttt{varstr} is the list of the variables which are parametrized; % \item \texttt{linform} is the linear form $t$, it is empty if there is none; % \item \texttt{lw} is the encoding of the eliminating polynomial $w$ % either in $t$ or the last variable of \texttt{varstr}; % \item \texttt{lwp} is the encoding of the denominator used in the rational % parametrization; % \item \texttt{param} is the list of the output parametrizations as described % above ; the $i$th one corresponds to the $i$th element of \texttt{varstr}. % % \textcolor{magenta}{I am not sure this is still the case, maybe I used a reverse % % ordering.} % \end{itemize} % \begin{verbatim} % [char, nbvar, elim, den, param] % \end{verbatim} % in positive characteristic, where % \begin{itemize} % \item \texttt{char} is the characteristic of the field; % % \item \texttt{dim} is $0$ (which indicates that the input system has finitely % % many solutions); % \item \texttt{nbvar} is the number of variables; % \item \texttt{elim} is the encoding of the eliminating polynomial of % the last variable; % \item \texttt{den} is the encoding of the denominator used in the rational % parametrization, it is always $1$ at the moment; % \item \texttt{param} is the list of the output parametrizations as described % above ; the $i$th one corresponds to the $i$th element of \texttt{vars}. % % \textcolor{magenta}{I am not sure this is still the case, maybe I used a reverse % % ordering.} % \end{itemize} % %\textcolor{magenta}{Here we should give (small) examples.} % \section{Solving polynomial systems of positive dimension}\label{sec:posdim} \section{More flags and options}\label{sec:flags} \begin{itemize} \item The flag \verb+-h+ displays some documentation \item The flag \verb+-v + controls the verbosity \hfill \verb+Default value: 0+ \item The flag \verb+-t + controls the number of threads used \hfill \verb+Default value: 1+ \item The flag \verb+-p + controls the binary precision of the output of the univariate real root solver (default value may be automatically increased by \msolve when needed). \hfill \verb+Default value:32+ \item The flag \verb+-g + tells \msolve to output the leading monomial of the ideal generated by the input polynomials (when \verb++ is \verb+1+) or the minimal reduced Gr\"obner basis (when \verb++ is \verb+2+ and a prime characteristic is indicated). \hfill \verb+Default value:0+ \item The flag \verb+-P + tells \msolve to output the rational parametrization computed for solving zero-dimensional polynomial systems (those with finitely many solutions in an algebraic closure of the base field). When +\verb+-P 0+ is set, such a parametrization is not returned, when \verb+-P 1+ is set, the parametrization is returned and, in the charactersitic zero case (rational coefficients), real solutions are returned, when +\verb+-P 2+ is set, only the rational parametrization is returned. \hfill \verb+Default value:0+ \item The flag \verb+-c + tells \msolve how to handle genericity requirements: when \verb++ is \verb+0+ \msolve quits when these requirements are not satisfied, when \verb++ is \verb+1+ \msolve is allowed to change the order of the variables if needed and quits if after these changes, the genericity requirements are not satisfied, when \verb++ is \verb+2+ \msolve is allowed to introduce a new variable and a linear form until the genericity requirements are satisfied. \hfill \verb+Default value:2+ \end{itemize} \section{Julia interface to \msolve} The Julia interface to \msolve is part of the official Julia package \texttt{Oscar.jl}. You can install the package via the following commands inside a Julia session:\\[1em] \texttt{using Pkg\\ Pkg.add(“Oscar”)}\\[1em] Once the package is loaded via \texttt{using Oscar} one can call the function \texttt{msolve()} which returns, if any, the rational parametrization and the solutions of the given input system of multivariate polynomials. The most common calling convention is as follows:\\[1em] \texttt{res = msolve(I)}.\\[1em] where \begin{itemize} \item \texttt{I} is of type \texttt{ideal}. \end{itemize} The most common options for calling \texttt{msolve()} in Julia are: \begin{itemize} \item \texttt{info\_level} with values \texttt{0} (no information printing; default), \texttt{1} (slight information printing on comptutational status) or \texttt{2} (full information printing also on intermediate steps), \item \texttt{la\_option} for the linear algebra variant to be chosen inside F4: \texttt{2} for exact linear algebra and tracing multi modular computations (default) or \texttt{44} for probabilistic linear algebra with independent modular computations; \item \texttt{precision} for the bit precision with which the solutions are computed from the rational parametrization. Default is \texttt{64}. \end{itemize} So using \texttt{msolve()} with probabilistic linear algebra, the most verbose information printout and a precision of $80$ one would call\\[1em] \texttt{res = msolve(I, la\_option=44, info\_level=2, precision=80)}.\\[1em] You can get a full list of options for \texttt{msolve()} in Julia by typing inside Julia\\[1em] \texttt{? msolve()} \section{Maple interface to \msolve} The Maple interface to \msolve is a file interface which can be found on the \msolve homepage or in the \msolve binary package. Having loaded the interface one can call the function \texttt{MSolveRealRoots()} in the following way:\\[1em] \texttt{results = MSolveRealRoots(F, vars)}\\[1em] where \texttt{F} denotes a polynomial system in variables \texttt{vars}, In order to compute Gr\"obner bases, you can also the function \texttt{MSolveGroebner}. You may consult the source code for optional arguments which allow you to better control the output format, the names of used files, verbosity, etc. \section{Sage interface to \msolve} There is now an interface between \href{https://www.sagemath.org/}{SageMath} and \msolve. You can have a look at \url{https://github.com/sagemath/sage/blob/develop/src/sage/rings/polynomial/msolve.py} and \url{https://github.com/sagemath/sage/blob/develop/src/sage/rings/polynomial/multi_polynomial_ideal.py} \hfill Many thanks to the SageMath development team, in particular to Marc Mezzarobba who initiated this interface. %The Sage interface to \msolve can be found on the \msolve homepage or in the %\msolve binary package. Starting %Sage we load the interface:\\[1em] %\texttt{load(“msolve-to-sage-file-interface.sage”)}.\\[1em] %Defining a multivariate polynomial ring \texttt{R} and a list \texttt{F} of %polynomials in \texttt{R} one can solve the multivariate polynomial system %defined by \texttt{F} via calling\\[1em] %\texttt{results = MSolveRealRoots(}\\ %\texttt{F, mspath=“/path/to/msolve/binary”, %v=verbosity, p=get\_parametrization)}\\[1em] %Parameter \texttt{mspath} states the path to the msolve binary (default is %\texttt{“../binary/msolve”}). %The verbosity level can be set to \texttt{0} (no information printing; default), %\texttt{1} (slight information printing on computational status) or \texttt{2} %(full information printing also on intermediate steps). %The \texttt{p} parameter can be set to \texttt{0} (rational parametrization of %solution set is not returned) or \texttt{1} (returns also the rational %parametrization of the solution set). Depending on parameter \texttt{p} %\texttt{results} consists only of the solutions or it is an array consisting of %the rational parametrization as first entry and the solutions as second entry. \section{Credits} The main developers of \msolve~are J\'er\'emy Berthomieu, Christian Eder and Mohab Safey El Din. It relies on original implementations of Faugère's \Fquatre algorithm~\cite{F4} as well as Faug\`ere and Mou's Sparse-FGLM algorithm~\cite{SparseFGLM}. We are grateful to Huu Phuoc Le and Jorge García Fontán for a preliminary version of the Maple interface as well as Rémi Prébet for a preliminary version of the Sage interface. If you use \msolve, you may cite: \begin{verbatim} @inproceedings{msolve, TITLE = {{msolve: A Library for Solving Polynomial Systems}}, AUTHOR = {Berthomieu, J{\'e}r{\'e}my and Eder, Christian and {Safey El Din}, Mohab}, URL = {https://hal.sorbonne-universite.fr/hal-03191666}, BOOKTITLE = {{2021 International Symposium on Symbolic and Algebraic Computation}}, ADDRESS = {Saint Petersburg, Russia}, SERIES = {46th International Symposium on Symbolic and Algebraic Computation}, YEAR = {2021}, MONTH = Jul, DOI = {10.1145/3452143.3465545}, PDF = {https://hal.sorbonne-universite.fr/hal-03191666v2/file/main.pdf}, HAL_ID = {hal-03191666}, HAL_VERSION = {v2}, } \end{verbatim} \renewcommand*{\bibfont}{\small} \printbibliography \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: msolve-0.6.5/input_files/000077500000000000000000000000001456710632100153555ustar00rootroot00000000000000msolve-0.6.5/input_files/F4SAT-31.ms000066400000000000000000000000571456710632100167620ustar00rootroot00000000000000w, x, y, z 1073741827 w^4, x^4, w*y^3-x*z^3, z msolve-0.6.5/input_files/F4SAT-byone-31.ms000066400000000000000000000000571456710632100200740ustar00rootroot00000000000000w, x, y, z 1073741827 w^4, x^4, w*y^3-x*z^3, 1 msolve-0.6.5/input_files/bug-2nd-prime-bad.ms000066400000000000000000005243501456710632100210230ustar00rootroot00000000000000z1, z2, z3, z4, z5, z6, z7, z8 0 64*z4*z8-1, z4*z7+64*z7*z8+64*z8, -z5^2+z5*z6+z5-z6, -195045312*z1*z5+32528928*z2*z5+97544032*z3*z5+63974911*z5*z7+195045312*z1-32528928*z2-97544032*z3+593425361760*z5-63974911*z7-593425361760, z4^2-3*z5*z6+4*z6^2+8*z1+4*z2-4*z3-172*z4+3*z5-5*z6+31737, z3^2-4*z5*z6+4*z6^2+8*z1+4*z2-4*z3+4*z5-4*z6+24340, z1*z3+z2, z2^2-3*z5*z6+4*z6^2+8*z1+4*z2-4*z3-172*z4+3*z5-5*z6+31736, -z1^2-z5*z6+z6^2+z5-z6+6084, 4096*z7*z8^2+4096*z8^2+z7, 11965912020956822071826504213340945920000*z5*z8^2+29205085086418176*z2*z5-24020501119680*z3*z5+2921365305293603749540390058488084224*z5*z7-11965912020956822071826504213340945920000*z8^2-29205085086418176*z2+24020501119680*z3+666533287690084700963*z5-2921365305293603749540390058488084224*z7-666533287690084700963, 180822883216207348160432743268586552751704827921246139786763981565719406974054900790208096306189711268428205525487307193961536322701982122463562618118112527738470400*z3*z8^2+12137512193142194609944512148964174594438222259619638237070390736728972705707423125782519595490526471786854487378662125960109306798639551757218889764424242142031966621532160000*z8^3-841545868948014128691348308159187312868618768884582741835035736545413357265077302366633842878563750509200531503674959673845527592846775183139587356128*z1*z2+349124919069508436667324617679219031956091657671618251210208494777735515149144699304631726465658546270445668770417088443670710246147406613882681610376*z2*z3+7058254055106392048394664806742226193310228950260644426725868303813556734175041665256384274408495444271596274828954543936567080924149396771828808521320*z1*z4-1180232865658657351716326838182655406907237093000632358346778177200542889101812076526969043854190419019381558948375252007885617695611313291668952962956*z2*z4-3531853954789516529859046913826230557345602819222484932716719393231672445587733522623969140585941788728294774089805816981559166096566995397203508184964*z3*z4-54394238079450159096774375436936198651087620910105453804061435652834264930525648563827410262475757547471917891414484054066186583442089477963265253048582636*z5*z6+54417121664013359379115375410751338774057499017783635883594446868565209965229533112168894884901453924420183490006120806474168414982031013585853457050206665*z6^2+9103147493561292705738930305597307760387411595696132137239704697962452871619680355913334806407110818124024086183741102282432352941306610554416628021228991754786*z1*z7+4523165465912962105049190214366593580374288888082114603019996620006446848793237990248440911031901262292543655107059140279946522805071276748004487852580344159105*z2*z7+39619035364379927375338882359369452136916414018675979065010645651152312225632179037523896949845581774382763771451558706202861194647589635137065414661163756017355*z3*z7+538987995686527002757485139335024244810987273262690494671745236891070725586787461605227958967289886347624832607493978762311990018853649375219562430088612215598102559362000*z7^2+13570870468905118634761426935256124492117677020767809475390616582294081972226682471256648225870055864223612494324441840939951805572837535799477484968161118105600*z1*z8+6726065701756043082280703012113525450604687535932115091521876191869217513867162308510078412862779943207200782305480537470106729987699502877033739578857206511616*z2*z8-6766926270572683994789177337214988517490791179264367254799410043895996155091311573023951462556419261684850392938394355446397258404231900093651205228373770762240*z3*z8+2961294061250124736322797625963289292810990374315790145631941212639988566864790594211589917957876118392101016328583348212983815106138256105866401491449458254380880228773888*z7*z8-2214432268709648733875585850949354830811959485697460871139208886281417388461782293839493163749684415821917299173701593157397388671844938813794775178849759147174341448181043200*z8^2-1124029331369341001061813223724303803635734770734692703576944690223278107090453742526816822059194892016879832643917774399123236098109069860924728469777968174*z1-556483595803622731718779290050819225216865867150804283681226509691628004990507373014118704427958230882440778604255680189732498728547866001851087781219206743*z2+561142530155586375221902083717575018226385573287146331243228902102162320836114509216009349931377698708942560551277525366629775034398693111579068393110127171*z3-21147101907311547107105099894942758700998810541347546446454555657492611665995356551067018693594217654616872192005920084555517480868622493557224813797934560*z4+54394238079450159096774375436936198651087620910105453804061435652834264930525648563827410262475757547471917891414484054066186583442089477963265253048582636*z5-54440005248576559661456375384566478897027377125461817963127458084296154999933417660510379507327150301368449088597757558882150246521972549208441661051830694*z6-540632561568039201605707389764324707148679905402197190554037063557785294301395533652981987310311278310588991394420743183246020193983225340508098411304336977031679937254789*z7+108876447089596807522983570249345756475671183145417942646859110314366623310827686916149717542372530817947558284883313146204217659569374247712679639637126819162152192*z8-3382322954528135748372279796646173733148864914534292341702179176306985124240080218477826187484245862525528852072281812548895895354349517167258164033862139672706, 162740594894586613344389468941727897476534345129121525808087583409147466276649410711187286675570740141585384972938576474565382690431783910217206356306301274964623360*z2*z8^2+2517785524276220051042375104281476170211434773378393659447568255066202758994549198662344643334019588718521524391396994159491130059308397870634636202063839323649103891660800000*z8^3+485871047602949309243129263259453720298385446009428036185393889695140951639988329577512553550890789053066181000089407746581786044670691510757042701024*z1*z2-212212864622152014406698051546436803554295192577115599805382046706596380375375724187746533849341819235265099978687746056575945719497380206040714485240*z2*z3+1346328310361980855134507296911488941665341180370088702935633658305944460695839789060504144475598043522235162871256725106641235871560447943319998984296*z1*z4-223011652653092466378583367324029613376037434786231703287885000448036908478395454691807502468326021294684127472859128966823408932401059871668564546956*z2*z4-672877003703662861582202691105148457418832865413354258580672342296318794212404037332991127025477738410707319047880671250231236086104718663847302456004*z3*z4-11926171910753378745889166139654343640072901226535800672494308525687364609236574767652160531567068942974145572011494986069474583327609497572159583620830249*z5*z6+11930275161513712390528486263920408697421290421454190273110812409053279819200327105272844178090250113779048309904169903410316084522656605475661961862049797*z6^2+1617162101485162178202187571487783879099016739174473733253942831439749219924345486984253853294469830655406659313121671474637132788639639955571769858104570639258*z1*z7+40574462710438306592988114953424791554162035164858818585690840429749924426528140239577151721916448533519348982121841602380651666026274501263274034769339076371325*z2*z7-811347374378101644160026291429001472033802798466602465917939637810963696942765579989286702779025054583875278682828692154939090348616369370401667073185746080289*z3*z7+116034875570867836767077017143012418670668289422353652028704477992784238996730904178640160919472532455028725613731927613272846095236591407891106722417562550875072859226000*z7^2+2408796477982225427008356699111919879067137667716716469833043890919593680410168140996570674845290045493414326206824816683661961051819747080751459955909818894336*z1*z8+1237769676788317302147483036533399098894526028445297058104153178095290247165552026348077949444778172810947730570663676231217129622765926900136605249669773722624*z2*z8-1208520412537119587906731132646459044075491573526154636361705533175508758733674763202595009841613581220639698169426896498366735032713775641732545443764679984128*z3*z8+614308850953161713233174959239813661029336415853853591578375519046515610048278134590958876497515070182953813644335794614537794909539911270307113723142270336264534179033088*z7*z8-476633371800470751970966485307832207313207098686461213756511329299735694983068865137184942178692664136561093370448644913497950983521020132187661202076153543261219663457423360*z8^2-194885168215560850470965295430621195064592786135825876199529141591962282469003745762596050597696795732368145692987594495541395510192470984958809189767925750*z1-99777862016235918947612145941212405472403454439706899356947886856920977746729414984372578065047140767265196584400343652221629765241463044638777667028333947*z2+97816863721629598639398191916427724433353116020896441620826256561583723484906261796552944428177104913282577587842266978016647097730317753024288993384597111*z3-3979157660760725010035072570640170056737305985287088372029461772034461100643165707816057152581642360971668372427285138716365598737304644663059317758639028*z4+11926171910753378745889166139654343640072901226535800672494308525687364609236574767652160531567068942974145572011494986069474583327609497572159583620830249*z5-11934378412274046035167806388186473754769679616372579873727316292419195029164079442893527824613431284583951047796844820751157585717703713379164340103269345*z6-116365508740507715869591202114377578479254028734695343277152601084410021383884596894647609491360475100622651353830813223102141292176141757126675866356725774382077443706001*z7+20370674459259213640966914933963303909577347623350425773266739897196237411079360400009757410107890112942860806215514273111963662586835620881875058184197790832769280*z8-606398659539608990373942244397939276172093010614771188946735147800563696541235909989362009184355540162960938524269834227240632518384853755137663211689310452103, 1084937299297244088962596459611519316510228967527476838720583889394316441844329404741248577837138267610569233152923843163769217936211892734781375708708675166430822400*z1*z8^2+28005285425379191191334537822931573461918013080805912878587209721692620189081466749101033993559384976869879643630132324538820094124621665463504712761125253455989885536174080000*z8^3-4143508716354547308592997989079858319894035109863780387238205312375099346349504762104710898603025670873420268251320929351319690879949394815740484640864*z1*z2+1754354409683955395718414237303040011488298389451610965691412989239679814190088097904793546974178142618671044309917262386940235505547014280823221978888*z2*z3+16655620629304947080767373059049269715133750299710838240448255568283227283471979295810791018501028472157846853310184087144310894178565617284343352041960*z1*z4-2792091439286014596472847311779522589004597419603004844378177658387509909387024171118653136189931968853958884789337113280537195851764663413601643156428*z2*z4-8336945491430465026070499110279310914299381986447441188889505526033475002936138141837559462560159238912539623740973360679043585658929068046860941083332*z3*z4-122161239555175303023435180841330742314154561646129010036696799109656637199463152464581285174742031462424038280833053868124688695407357516396877486166138318*z5*z6+122216230467405171802657099847461871287785117161286782119064399840189326676097072991735046666753936692325115280815408394797896053849007329542157468479532945*z6^2+286891158755121215664029230488002366078725813025735503906411270946174529395817738408859676736705046256384088397792242090624591976990069766970571419144692249436018*z1*z7+10807454291550986640688476102359949981713909978902287949986380221763785647131132783747775906657908143449934054698350986353264349035518323510894502566823782129065*z2*z7-10924526766346404671672404500525622452403125633653206694230005779472965059999700614211056634148106008227951823242062075303789398064042960269900043895690533573885*z3*z7+1229560399376431091934084114720984038298469274818259979176980371522137189987091805513413928411952914261405799070897094901923108921900084591801347645791023680357697327506000*z7^2+32718022481585599753344668804483162248798309265739265192468485338623545883640765311124845418417478264036547238337346285315142297473533716092870472707600719257600*z1*z8+16069733826212241827863394708366542320553494289421643227203147441515406826442170256018219392325511974181803275820587874130907897758279977745727458492244639019008*z2*z8-16289737496857507590236009131511928005383831541333026376470216617482992579811061801996523306984058821269289771863649941884257465237309579215512392865204200632320*z3*z8+6832617003314695968224216721996523319451091643911375172224803013377944474123363578019242211577555173353665166888781917465576242967328203660736205182478307970130768671698944*z7*z8-5051966719765474932870311696305766142027630564129792759179398481053915714955221908172889997252390189010762117134619617134051345198092369595141523697275746086558105151124787200*z8^2-2723314660485349847864786280761374321866189058467694716012384807012295908755789430483562056456160322907596483440342041124849777152414179386822795708796858462*z1-1337288627812861610845556320802844877065881527459945498677884805980276294068262403215897247405050756661729057867546948514814875172983144444619528215674795759*z2+1357792752753499434892813560004547835975015233197776784986321437054317184653857891410207421208781705234046052363681985685695287849463356660625539377134366523*z3-50073790581045268315788559149410936426764327614378678530115829367811086517080384621819849285413699582485212995884470276237203621148172930451648641661258280*z4+122161239555175303023435180841330742314154561646129010036696799109656637199463152464581285174742031462424038280833053868124688695407357516396877486166138318*z5-122271221379635040581879018853593000261415672676444554201432000570722016152730993518888808158765841922226192280797762921471103412290657142687437450792927572*z6-1233389565258584336325664811079640101687248094778879264363243186091262434289784522391902256568581836327632749006874498263141685545854715334434737493973241540053558046338957*z7+258531730175417588835861788875891318402443723174544808502601265787993210249211166246925014412070608979794021434032057727988192817074291425612204743124083241656100096*z8-8128274693741521907185752138934627182384980419165989563696719987492214777628359090452987438866115404067249470704522536811734057282274217397607458705254574971828, -8866537191197759056698402007626775234215676607329362930140530873546530348833445419928309393203169532960066968035585947099088468962420430875082594404153879444855143485228818772706826125312*z7^2*z8+36472806513454379549940586322478039274313611637105930823024822956822303888075975458583374369713831994032293044705884346826462043172940077359937446415819000989636335190071366300965288673280000*z8^3+1321918098219018607633202887749572754679497864621700271234024929484807560580173953873807845641759201233568540225036909691974098600468606444943059308045204733422816*z1*z2-292016125993607997392493933921689188348606313303041603757705114671882744173893607248975545860564894404060637629982066346198378402979345419648304781575059941988200*z2*z3+35614994648279758205655605347936159900576893324694207335292787591670973540944824293921902579348323597055407640403409425806233635753866585193923354966873755832331960*z1*z4-5935115818085568370335356242732459617399978242923133776863585887017059384653344140832741467031475050004208605936540738080771188761059664018698295411419905084104420*z2*z4-17806181077179366401726176153036875349710809235332544248297109248535517405776331075029209678706700633353609606235887175747412191927683505665685475741843072004479692*z3*z4-479634506927837208748065817006868222758614781401181601358190585371283720697186099646651495487673322716389716314143606416642895873345150413262042334687964454065734883120*z5*z6+479712807374911051410465956219170778201438869225704276110715562918877140540382956520722901451620706357470680972178871547738160677127479926949518647180650972085396186747*z6^2+35278417302801957989495688642939332878823447844106753128671627476107531433051949114022222913198287449846150474020236574671202880771879353570306843959568011843502684223250726*z1*z7+17639517641037045184966584082269117005057537315278249316512280044117795755691495381798950821659260796701839381206092928460448145240285994786003044396706095868065050625256931*z2*z7-17672457643350861673718525543287158153026938648590720338441942957189779377873231391505787798385137148436899051807001984070794052426612239131767796767457653339597773712668543*z3*z7+13796535065417736154222450778520975417105776356373158501086519641290368748791054908725885747424461302775701628338951609510979293962564176822737817984785169482489933641155763979506111856*z7^2+52532349905844948121091304197885548223234922248713284137923976008871761926233423059722815693312326076145867069044764113086760932551942511815731425478294024479454091916308480*z1*z8+26240569263349559749160567212654971943259046661174439449079603391850528369638170535507670636600290622639012881476105299904846865292472365412801752378209901685954376448743424*z2*z8-26315633465734973476455546607090119777807217194570461825444389121450422165402243826107559813865205311743913792958915088286598316952420605259496063285960307311331596926883840*z3*z8+8904480721055463136386157899417047792029814008932851163116699042057285073507184472622608591397896036553772613695773837897562531975710846571566896822452296069743761533962217380253445312512*z7*z8-56568905523164147888897096450685166593157154457664823101764821724586269706203546616077902141686108310880601933431826819888961252248101676224839096127101834955083853977516160341804520960000*z8^2-3814080616409422200763941177952201466787857635602657724654649187745284000337672899181720238124949420887417807952034206276311140824062418572814058436566018873741701640650*z1-1903408533204699300342635246845596918019376009340409553833055799912373328267797206507680088574323507601211666131126880199124046373671436480265784468657924891387609367717*z2+1911531146140259575995686149081354861262400803504524486220482890899779103346115212563822538269074300900261990221747817636430925372944419496300240497374665388311136334569*z3-104884843753493236390347491301884601390292479140357193167578311033619262216832467264753915777826262309643387666174501057273637071653757622737384362850359889556180017008*z4+479634506927837208748065817006868222758614781401181601358190585371283720697186099646651495487673322716389716314143606416642895873345150413262042334687964454065734883120*z5-479791107821984894072866095431473333644262957050226950863240540466470560383579813394794307415568089998551645630214136678833425480909809440636994959673337490105057490374*z6-13810766225908873470634131806612230046293727271881776496056332082710319959397714087447696286947141406264621365398979988183289642154921981405707251887373843081643376414088908003494314223*z7+501325923115085038983189458647937177374501074059979201788684672458053253585518259942126730334306009650736816491538430359146482320642346266496303360268093124019935717420595214080*z8-11560534972409899398364616397112905073870098977737768751843560540594567731710719447030430827341020428966289287937134438404487431365346442315025569596025651047419000719800306, -32372883893479406721000682145731115967637625018080722766104750270160316787756109834694213288910417006815751320890786872760388160857175752707625183778345359284424002199224320*z3*z7*z8+4754731687549260241737228888351162076809155538936220335814530548494309003462967813312573237399371919809849559964108557953437300909652377168414395871196396149609783526068711943441612800000*z8^3-375335555638162098169635142756457890068215568574407142503526147142105784320059466076154258678778753176434597511840956861365652150310321729860018717589910575959136*z1*z2+157229976581518205989763186846272009502502347384059709641037347325078795849007725221644967572364140344681250515718826855232957597040482535555045693945585799240200*z2*z3+2585192320208058507837506010339104194435404711528271156983362375543370925620475230060402014051486600584909937016519698147031915241285488196025175817748447976207976*z1*z4-432566136045580300024118860661292182905902648024263069956901881454608497475666447419711384560400151769697088326430723899092270697175620157934768536661047729457036*z2*z4-1293773014526134414148916094233894613271022121042255711005290560742768754633810400711840009548350647776413547361543181724964638751396912252207352936928130477808644*z3*z4-22753574346281922952999120734265417344586434745142335424536081483097869004256420428053776683746247450413059966222709316030646512514487442912533286227357220579101929984*z5*z6+22761591910346071835853930634400408265774299879524168635934974808441128055617668373383723628840744421021928757785850446482261580914693886650227671260058008948719359417*z6^2+3253593356163662550802001244313596819304942681463537429625420783033320347676429361309026611218897650204001112577518538108058298941888359379767638634899830277878297448172418*z1*z7+1611559482964391194250966045343614329498185281278205110584797012430776997333004768394996821955072599093694316473123290507561841873119791905955218998315973907288221622446385*z2*z7-1612275058010003640124508329789794425179566903307890885955243438240922761799947432634517331627179920409638115983170035485977019868926602535574460514079105343607826405004709*z3*z7+217220537942220035240626470226690329240748035554868657925366243254692218537207063638905410840293887480323966377315425015630151246137384525829469284532351500971966483761367446014306000*z7^2+4847197755293630691360720362574732068202235796965268055410441913543783267243091481643657701600477338257070074253627418055674597705192745813678166677512091443340432238514176*z1*z8+2396964603114900471259225647012708337637314805045474489655985917944065377500551478437616139746423390629990659369715288576379252158542726935518650586141971128605252303366144*z2*z8-2415132433129081445422327413408663503631446606904943408885051735325233737678770174018556134198632321542772537581210753844683685260613757840597393840062459148883572070688768*z3*z8+1160085621059087883626238249944995205531212070908029155988011059347746068098958297920304191623919944752708189610314930520618387524928269690046370549167140781885407779995127026544734208*z7*z8-892313352840229393172017902749990080512276398878141187718966418681030494347655666086726355814079707436706201311221384644052366022867509988016031047048816080376447959386406756171174400000*z8^2-394705602802510986573865808174558437670160367620564775884908017593525016389710774218290733449539439340028498526164861343262484489923107060835716500998800151010038579150*z1-194965178369844050888419906989920322161826098092166450438224484965817132454241949703827672717635447567229304201715735013589206696696805141040202509963629794731908304167*z2+196982295895106411845367093658036306892774653589331051662527224713175099032811007245930755569309674738529179379355116686549787506168863435048693576014710590111071071571*z3-7730834010606362801554653504778244035090914625193648203497593882264005788660651500014151724284199576141374167273990103438861228136808204256877736250491153421961001648*z4+22753574346281922952999120734265417344586434745142335424536081483097869004256420428053776683746247450413059966222709316030646512514487442912533286227357220579101929984*z5-22769609474410220718708740534535399186962165013906001847333868133784387106978916318713670573935241391630797549348991576933876649314900330387922056292758797318336788850*z6-217849822933549380537326844985772941364306952733294071405087120629496603999501798927465868193868963160536782209964728254085102696241864292250544703631210294321198456215118437905078901*z7+39489008276707621390187489800986245930053230465693263289801947699714850548510174236792306979881338101455764831576064853222810998963231302894639208348620355358153604106541681920*z8-1184929281384513872774023504865943352022183777798998705558099617239613263443328509794391514188701254176456062100498350751545471570132738621488439707678580634415890160894838, 5395480648913234453500113690955185994606270836346787127684125045026719464626018305782368881485069501135958553481797812126731360142862625451270863963057559880737333699870720*z2*z7*z8-41469704170217898624419277948475792235309100888630863754958139230907471501656910468047615819208031247228169521061210353949873455784028816915081594944287383004744283050791921647616000000*z8^3-30888424098140501692876190409523744658948688552323105456846442898813366123062791693940001917404409678981639775626257395887250879489935461429317840338319969869184*z1*z2+14925153849184893212781623449396679608536941883639111085865086424672595712279717360122755908813487867590076515805057095472176938880243596246466803417588485374560*z2*z3-22203431850243716232041628954744961117903058981286211731719994151995773257644921534993591596727875965472098260905870423460638936501768804612969250013040284148096*z1*z4+3602873631396569127154497843502485162422131653331085122700865537690599799138602040622854242303285148341797164341995069467462984648203047395699097155996150399616*z2*z4+11096776651317378109416959971885668808314245455000347717841936330052589910048028778061101751586905055581618831642013703239657951076407243410197650718375191454464*z3*z4+175912799953177589917695717416167878670886457243384197599663597494692300300918640302887606098273561227807160088325915740258609742874211947992176253849692943465454819*z5*z6-175981535870810474609933695830988177415401067047051719543259219424633640008928850290419607461585519694678352224258321396131507437801181260327873667857719341329190212*z6^2-24688799580535805917384603842199699310601252799541852834470620144352014128920565950412313216056046527334959613724781110430058658107345086047572483093363143805002328038568*z1*z7-15633715797450561758312831149192480602122180861050286355399649900909257650205592346123947445603360290382033723552701672143253224386109135002226516198535334700272770316820*z2*z7+12391474666335228497023476058933389972409945315717779798390991443808992070788532174772502944728578221916913146332524046278555566579205673160342851530983235723620866156644*z3*z7-1912599112381022834773630165691925385722708694365019934143680919890233473400720867304197387256641737962307734458121695025519626834606661698273564139629977652118244910832683011656000*z7^2-36778126676183041933194174534550685568924763251715804303936965814767520857485326260826679437615584579825588377553861207351745911401511692658855471550434341031751572187136*z1*z8-21067676542970231701690248370597273623195331123720010232002000958191872184324544857745124598536197641781035163756622392256343203608900551620950507951518947078085453394944*z2*z8+18459207661178340433699232441015724798963893322498748953746833109310342743662535409796091656525233571943089970449730244877815765961936280535075973124275679857463443862528*z3*z8-10118111153290807274938020613792424965499720271296426058206159499381384048816526903749966347073655157293510539857172569251935239086167388357117599684607823466915220085208794425540608*z7*z8+7856292688119390705250473648944914397804765253983368676356228786707553737484270469194563676887157512013291984621643113338213175851299708197046829043902012513092336094559343591884800000*z8^2+2987734025948555172713402681140350832282793980789893188881662493830559487297242103342320868299301998056323402318752429289439280289005099197473022804502809388586443160*z1+1671421725851227835331304347882125334160070301726920979916838676364570498773750742847520536726884907530058712167592748308126262332824119504788357504927709032354045132*z2-1500213110691120143754214772076960686285906703490708856324472326962490187980038559037392888869390917506521089803500955738519369980195020074619972691989629279073610236*z3+64017603508849629473367599412914871353670070531955850622244819762190193193115421288068442874857166439458547815851580249159379015028092888751719437581531787257205228*z4-175912799953177589917695717416167878670886457243384197599663597494692300300918640302887606098273561227807160088325915740258609742874211947992176253849692943465454819*z5+176050271788443359302171674245808476159915676850719241486854841354574979716939060277951608824897478161549544360190727052004405132728150572663571081865745739192925605*z6+1918039211276383001964233503378935642050725455555510562382752216114770929562271489495875596911726733597761534559492694141073056602655949069213057000562117202055858563430679979044676*z7-335605909026327447894800525306081026211397165631163680863369692099372046775405816913964218819966029989158754997627217188382445295396355636703481785161145371135865241838658560*z8+10158203215713376861940344974341267969769777196148149071340509946798648016633855627099304572874515665652846767442016209865997321825839315876992405526899565232872789573483, -2128744625578129654512620887439165935731555154895987030485270443541694347378340281748756422088470623496021786677020343433199944820461992615987189464300204457302252322816*z1*z7*z8+148070771733240124740422093908306873833499146305779992899471140683940489384743688887575237921016309389672712759722654404902969123141229990675586140273510060867505099599622797393920000*z8^3-18430705222197903745493926075522596444755332684625867849924519862117036771424762153168550803585145733508182554083741095017889463930231194556556841189961295008*z1*z2+8112110510887608786700083261261179351678622909129998156365786048684347280079354523853008886588152700837635378404612618269728004450957759991835227225013138744*z2*z3+80469690457472540752965597099244968659217766246921116672320980780984949944802641069410836936565617153278209660283749376749665350385743623795710100794018641432*z1*z4-13486783188004176652855292582977142643844889196355056077562545222127878984333951791271838097872544094901703860634488998621586189238841259672345707764663570868*z2*z4-40274498028006550016954316177820521379862243464327833143750279932061289805278711681352007503441969017903984988289932788246076940032137909313230482692962051772*z3*z4-707814377440738142302956923258337251063974232953248006138163486938100840097541526222800039119674492672648310512451327671288026660629763011613468703997377265912850*z5*z6+708064564385086746708380113873734645146341320854186654941764169085764833515414073690083825261588354684690877280928865384195170355611158583458610277490801355050511*z6^2+102844297908569329770289682369229677170000769126098328693949460629222835724770278327185527872406155658433812501816592218661260251362651198150560228594108694258357946318*z1*z7+50272465287378416954420368788963140226774926162927244250372294453588001122431415101755255893956609932678232207633148062000018095327162487538821375784473294634728674295*z2*z7-50935404561682491011943719556354359950501568213312433460987589117900614043915955209894993056926245902829857571412663909133377658115803216736009953612832914848861661475*z3*z7+6761385391778272336075962197357328423607905459852642386917072475155305309262428958509526358758507072552445211541867765898002348161143094386306458497317528454542683920574162350000*z7^2+152353180858678573945162393393669479963429867903106076562041378266648474917318857033982866113435513747579690627096358059711560300751263188311501861429554614611949019136*z1*z8+74772799997611833176812910544862371904736602440744453984564177262415907544163729705003171697432596441232270672280489488870548731546913253676814438513669078981509550080*z2*z8-75884375958374715313498504338504637685995363962158311392322404357365379961338814845643850907488011743872504070893652449957003251852262985660512356007313469113620893696*z3*z8+36127104926290501231589698396640514546025636831637517230817334833840713673717169292987922635549031325807872271091367164060974270395213845485325474828961162229190816386555178618880*z7*z8-27774951710859121543599506468591271742486713835506116494127731712486212918521288770903900016517565240299135929374833012787768945362921293106995811302096614343077375408066001354240000*z8^2-12394728045723993272141430402086388832057876274323720506200607998687282138279826812802626734332527208197676100190545221945591185679953559607496876058029107084982626*z1-6083877193724477465630567181999509050139167282032623313777990034108858857876025218377918733031186293599988870241426294251388653631092210244189904063680576930091889*z2+6183929267469369671650386153560883991265106962528048090926107673546009769655319579445481139572238289739182495357762553752924468116548345032552630094122945697506469*z3-241047708787416276630175526576705983708613333759718690255393308430156604986719015421571589170177496336707484581063526375745284376439604644233880588616473775954008*z4+707814377440738142302956923258337251063974232953248006138163486938100840097541526222800039119674492672648310512451327671288026660629763011613468703997377265912850*z5-708314751329435351113803304489132039228708408755125303745364851233428826933286621157367611403502216696733444049406403097102314050592554155303751850984225444188172*z6-6780990431130876974505845748015912463485466625049831359769674687967512173806285127010698346486431332468419775881454542071725289668186905177868696830491665134745599561822980666515*z7+1231449225263783982990774162930680876596744016547397958202363901777691614564762879044826508983080927178074954670352821275922412662351653884323086840558871010091005511891712*z8-36975773291020800336746904957095023702495391580900924980138310469321934634168848768158469606855946986252167567507387175472966459442299729561394335803569000940844551916, 18223556199133396806793612407537238519507752188938087525384807517170158984103970470263159705858181838771280088115517678141436082522309135779530920107216028186142720*z6^2*z8+8259621100182228410740363566570965966923884216907632154987958568423190039371030643301334530800873951866178952792298220065979527130879738421711119302630451203787774242432614400000*z8^3-289619042000889599945232821612284176981625822183349242960253879052822127344313666443805723107336339833774492581507099946551581485589418408219611905096032*z1*z2+129504672165495695199435313396300746542895875513964161004261957604260741954364782883379168998666041665383188595163697045714509726576497293462499190554440*z2*z3+10348024260391357389315051682994582841595908615497299111337588073721322469419124506418643790674671454788181064196453662758432522343901462029866560555407272*z1*z4-1726500319252422071942712245642189927138616508913498042097095744599140758499340847784880838072951706114843828382254676566257713951382502129683392425002732*z2*z4-5175363631774272523797050857742967045266921897887260668889453968214373657477029401490758416500207944429175107180592500827804783003742676062544725158642468*z3*z4-3919368684783972221958258210249258639061941304038202121546947006014191107748341516481351771825668281783443302957300365003927368076898364507371054947588814024518*z5*z6+3919345319116143924945238245143211481357122134276482624033312627841754772811331643251702899800699406946565802326564557069253433035061570527293982291439383881569*z6^2+49613207429719771281694829864353658032007876003016612213452836600777022715673547736842297559267571883326815896550995815293385039952805701821056419710171490922666066*z1*z7+24791891352677756901049844055180197549303970091768875848792077165604704482758442517807930372449871554022872820110566293464590444414276355150364124016278969566104345*z2*z7-24805211996791872024192284130881508915153697039020833465409472975793626021844098698885794994462446125083202458789977668325814717764081295589529097588766812899211053*z3*z7+333044598180419997350409852703680523303491108651990414082717688329080832933040249876168958217732445763097722706397186116739091656911365440579860126428536892870208371326322000*z7^2+110274048775516615982085990251885157909352674904765326868718161996411698186759028719579257785660301251069874449984052385805711440926440069628078999538004811031027712*z1*z8+55112477031880838920861554645029483644366670205301702604763283031551284634291422027683946628161962881820753142388363733819379483477367177367543081614790423690702848*z2*z8-55134964559815165090589098744605150142346750318210062170242986732072000014010665575057736128982667307210884997013168914176235311223598332961113395579205465178566656*z3*z8-36447112398266793613587224815074477039015504377876175050769615034340317968207940940526319411716363677542560176231035356282872165044618271559061840214432056372285440*z6*z8+2014506615216807830556965217528517512252239191752154864834369804054462624000068065589322490645138006466584686939012011362354028912827420357746653779999713879274181959268888576*z7*z8-1369519694415175899944570136983582879727206585121465762794933551901270927030678174741809143690815821407542839940263888644956162850393915657435316157410167199487884376182694400000*z8^2+1131491644202920744632001292718108954879723334698628315622129493525950764103219476221920691750646674542554653616593959586214168684457335288622493094142676958850*z1+568937048629532395715333211265104022573617651308523903880336909790518667735216937456074045653915314812635349084544937383093539065116024455704525665163049346561*z2-565932035552682964214428526184103824823430147272084692894081950016861173949674975823236383809467610824301665926818106384415512809947083995337972889623507124853*z3+284704172552737991930434456238948822765095103042715123513124553283357665800798252209602400301747885286973547552824804779064854479550435081611876062202329902024024*z4+3919368684783972221958258210249258639061941304038202121546947006014191107748341516481351771825668281783443302957300365003927368076898364507371054947588814024518*z5-3919321953448315627932218280037164323652302964514763126519678249669318437874321770022054027775730532109688301695828749134579497993224776547216909635289953738620*z6-334354879616146106540327586591042040952799393910701523932657457854484143674229556029614881063926669918526427036801070529535152106224949463897649638628402776455587212414636477*z7+569568613595981280711288163772188324022421590821966392898713165965031243071258244997174042246306505166881705806298988177428738810312472107976021662568609654113816915200*z8-45510106600801252428352211223848094943651110796165977723824186913338583308614564937415632645132275008656256786987629355825875751685597009168820955336014904540206796, 13667667149350047605095209305652928889630814141703565644038605637877619238077977852697369779393636379078460066086638258606077061891731851834648190080412021139607040*z5*z6*z8+8259621100182228410740363566570965966923884216907632154987958568423190039371030643301334530800873951866178952792298220065979527130879738421711119302630451203787774242432614400000*z8^3-289619042000889599945232821612284176981625822183349242960253879052822127344313666443805723107336339833774492581507099946551581485589418408219611905096032*z1*z2+129504672165495695199435313396300746542895875513964161004261957604260741954364782883379168998666041665383188595163697045714509726576497293462499190554440*z2*z3+10348024260391357389315051682994582841595908615497299111337588073721322469419124506418643790674671454788181064196453662758432522343901462029866560555407272*z1*z4-1726500319252422071942712245642189927138616508913498042097095744599140758499340847784880838072951706114843828382254676566257713951382502129683392425002732*z2*z4-5175363631774272523797050857742967045266921897887260668889453968214373657477029401490758416500207944429175107180592500827804783003742676062544725158642468*z3*z4-3919368684783972221958258210249258639061941304038202121546947006014191107748341516481351771825668281783443302957300365003927368076898364507371054947588814024518*z5*z6+3919345319116143924945238245143211481357122134276482624033312627841754772811331643251702899800699406946565802326564557069253433035061570527293982291439383881569*z6^2+49613207429719771281694829864353658032007876003016612213452836600777022715673547736842297559267571883326815896550995815293385039952805701821056419710171490922666066*z1*z7+24791891352677756901049844055180197549303970091768875848792077165604704482758442517807930372449871554022872820110566293464590444414276355150364124016278969566104345*z2*z7-24805211996791872024192284130881508915153697039020833465409472975793626021844098698885794994462446125083202458789977668325814717764081295589529097588766812899211053*z3*z7+333044598180419997350409852703680523303491108651990414082717688329080832933040249876168958217732445763097722706397186116739091656911365440579860126428536892870208371326322000*z7^2+73826936377249822368498765436810680870337170526889151817948546962071380218551087779052938373943937573527314273753017029522839275881821798069017159323572754658742272*z1*z8+36888920832747442114067942237492245124858918016363615079378475514381125650187451557420786922303781043049473054272846055677943400955058041588012161507574395504560128*z2*z8-36911408360681768283795486337067911622838998129271974644858179214901841029906695104794576423124485468439604908897651236034799228701289197181582475471989436992423936*z3*z8-13667667149350047605095209305652928889630814141703565644038605637877619238077977852697369779393636379078460066086638258606077061891731851834648190080412021139607040*z5*z8-13667667149350047605095209305652928889630814141703565644038605637877619238077977852697369779393636379078460066086638258606077061891731851834648190080412021139607040*z6*z8+2014506615216807830556965217528517512252239191752154864834369804054462624000068065589322490645138006466584686939012011362354028912827420357746653779999713879274181959268888576*z7*z8-1369519694415175899944570136983582879727206585121465762794933551901270927030678174741809143690815821407542839940263888644956162850393915657435316157410167199487884376182694400000*z8^2+1131491644202920744632001292718108954879723334698628315622129493525950764103219476221920691750646674542554653616593959586214168684457335288622493094142676958850*z1+568937048629532395715333211265104022573617651308523903880336909790518667735216937456074045653915314812635349084544937383093539065116024455704525665163049346561*z2-565932035552682964214428526184103824823430147272084692894081950016861173949674975823236383809467610824301665926818106384415512809947083995337972889623507124853*z3+213518406149873160653896907772006484798267946054675719117090148919411732269142117560136932700739362479273234708623563848824869782197665019973083405533517291921904*z4+3919368684783972221958258210249258639061941304038202121546947006014191107748341516481351771825668281783443302957300365003927368076898364507371054947588814024518*z5-3919321953448315627932218280037164323652302964514763126519678249669318437874321770022054027775730532109688301695828749134579497993224776547216909635289953738620*z6-334354879616146106540327586591042040952799393910701523932657457854484143674229556029614881063926669918526427036801070529535152106224949463897649638628402776455587212414636477*z7+424978362823007127096985944527685989299017208016884371950428756921923909151631317293488567350101225912610676767168442039635049572559840847417278459707930882477914039040*z8-33266154779508501448787752887534012813356839794223200167706269362739882741169709777707572217758809085731802977785015915824598383740920558566948618388979135602642156, 12634472448*z2*z5*z8+2076672*z3*z5*z8+2843875383871466520576*z5*z7*z8+6083*z4*z5-12634472448*z2*z8-2076672*z3*z8+115302192834752*z5*z8-2843875383871466520576*z7*z8-6083*z4-115302192834752*z8, -48596149864355724818116299753432636052020672503834900067692820045787090624277254587368425882288484903390080234974713808377162886726157695412082453619242741829713920*z2*z3*z8+538477735182672501852426797341913762986408516335863201462813633804441998859932660562161796363099956518503806740988017292648565509858376793114995315223497889246360899317567746922905600000*z8^3-49329120277148485637826655114612642579733856159408224380965527469156816432987509309378914243476125247229060926022878157291506893211570230756103729745064297729888*z1*z2+23582683646534136977570205866031505949047739928350114230545554287230188050143727737052755702429032989926304741834485371159708456653234142696478957289218437435080*z2*z3+254112612760739892685960539893568867116552506207992476501645379750649321164777524555165411039258274428596724321221557743409136049138989744496561054911361235197288*z1*z4-42537288064144251146839037781141652842200111486066810560721268389757725720399495274558966743309797153504763276306929858171556163544964561309083940607408858346508*z2*z4-127162012919062986008785454227535478613087394737854156852999186125936708687708559814798824668156407186576538353740174574103927646339921359273429497217034179402372*z3*z4-2890004260302816646951834408992019711233299724034258381368377692541225759519857111287468233300758821324539709022313069521875849104318494454768266133913293618181045602*z5*z6+2890707122219233406100767715831824181024329141946037140435200045299006655968834957825779702168227586078088989863959446582136379532353022284822838935570690479914119601*z6^2+301016796055923499219806486825055388266605878796658880142656178681407904522426546159640908010697770316157202747922087336079820580913842395666791570441185280547683134546994*z1*z7+147772313733595692556819459468774382580217402814085727170681157562807546316114300296132784640419897935023440747512446411747462664341047897493049480728699316374450758759945*z2*z7-150408370648989253592631795728586344405265539929180399625408588314489603850619906656976708688592277225574734695729417348654693402584720653270850736964371760383655070164957*z3*z7+25917300298707284649562002613167313326680143100481382975752040848862973372748212617613423766871608106104143204777304355850976913201222153255424916044265971791857088230757614851538000*z7^2+447690457532405046472240026445535479120976608556355675421184453394001167022773130069921941822960660036884029501261353728235202096040897663188088822701062418436392250769408*z1*z8+219917272396770826515204139071593347121336196000746323980941741135424822855206357015114027406145562919031632247396017280440546493296149771032204680675412158490617156411392*z2*z8-223698616955529867299637950787562957324720046193190005807106431539883931946132284032848338570897097478319395096096561434366516791017742389003942983162671400118853572337664*z3*z8+131387807915500087630374023860063665524983920139448142343639803807059088210599745131324989924323706735684924409249073648071605933807213045223740793968251732476108427221811260353572864*z7*z8-106435948469547613410737706078267565100299304159411981956914612926917530162047917699064054885961483191011805411383970414471754859990897305803714436767448701263811674158258039098688000000*z8^2-34849631966363224755930433764650292659890874879529336520955162966259657109583434888666487481617729843916043714481933526453715957068007703943113532562481980967853328030*z1-17090190518516340462367762360366533855427912851606265153152175028874822309852206673404924509730317465018959181820330545607868871998868843412175645545699069006895221391*z2+17411613061272613801305082699887291474889950655908125858027572040318442573643405538565823068399533283276233858533717057554767665739655932696078551023311853161314391643*z3-755648609679127127996136297225223858599746906006465380770679550547212436270587213751186672605176834442498654403498972636444473519293457036760661763178100805579695864*z4+2890004260302816646951834408992019711233299724034258381368377692541225759519857111287468233300758821324539709022313069521875849104318494454768266133913293618181045602*z5-2891409984135650165249701022671628650815358559857815899502022398056787552417812804364091171035696350831638270705605823642396909960387550114877411737228087341647193600*z6-25985327338639687678707464912052016525581969064696044407848495540301062236240265375425097601711454038410825772606091866807819230944414075026216414065550075633128765601576075636756973*z7+3787082180644093679384776718549681873508484257685160179785258120579625242933484523437457672315962070260936405836625932207433265191868592186129546559131492783469666155127768320*z8-103850093850559414573607050668145142718070468717931747108905134711433050570624768872947684013947333810819638058908741648865676540232865120897256809749013221547471559518024, -874730697558403046726093395561787448936372105069028201218470760824167631236990582572631665881192728261021444229544848550788931961070838517417484165146369352934850560*z1*z2*z8+6240069853090188449451499148020897936362339276826108597594267187516086992145216283582560757008568959837954128586495272779824195105312419791046213259890867411754701079866351375925248000000*z8^3-530380477177081104816590073333877931159724401544545548926872575992601458421058500587039908694897509757948709139484079679376835473841270658072370533419553375215264*z1*z2+272225581842901872696002199153852112335632709795543993929918403577449309277355348023309364475426909800297496216476013133057225150704447124399364569850092658454840*z2*z3+3029507919487138964912341159201695256453467694024389299330653118637177666804452726085241605373633671681201690760020265406890828340035155698574487676953258288751704*z1*z4-507004170859785654148642266036377164220360683965400721438962182591008423890856878170618465226790394873842520413574240013898943862241866213887534208224455670346004*z2*z4-1515549997498525727148544891689384511588377234376383479593303974477177520756191679410337719381852903598155875483840946100282328850343724935217389623123792824086876*z3*z4-32807596892202252111852031884232082774821529791857099679117561184491574998255058387392196320965547938012176216368288737443062734872634837437315261282649191409215162676*z5*z6+32816189208864089681695211764721190476382163328775940443083904382650419538392504707950765649986162341932085198858526571995323661727799641860847616689302879462736415663*z6^2+3637456782541572922580299064334140979670970672171215287237900793917250827499907364779756027066789198612249625042122225873756704353346943332093728986039392181066895783504462*z1*z7+1788186939081257663651376714524608456318758373382617479727188597732997193184221557392099319301287150794416483063821212565807799118730449847934220680830033279660178811749175*z2*z7-1819333100039082284583357367792879489144920915113230144081445250519989592172813097464432468662186052119210518030645179718332251102243052478534697384164404233028851408858851*z3*z7+297467343800640119611527190763808433010340242060115036702422170417161351377025552620516245791594792926369772628480480722098106173641814315703500230270263634445699403667544318015214000*z7^2+5411884781792665604717826316693381445127496294204704663577858632066435952080361721523672723937810230568278412494120211434791299032992692028743575575871045606747972781133824*z1*z8+2660866307183729254579951297333920638468557996305343507264404481293873575744589826986377425817801249969460477213574604277679585120605090990557007497561244286627491544385536*z2*z8-2706864641311624308443172803083597830705330669296089006722928558477729054851699194862179481748454982304194862820498233329206671348810508307763645369051661345150489577244672*z3*z8+1522552881997170369155052335858601255143885637707502618586425043006849678372873644107634468796336287691022218236451648086185673093266555979200043448065389367899887154529684594723950592*z7*z8-1221684709352414214674193351062663067286392544301471356428055521894217125158760581135848573044083897231136958234442362574999304033634533446201073866202691378363474967084216251299724800000*z8^2-425611588678726500971419731020368648031178403063851188120932727460514140014427810363279584103192382036523296322126530082317159026656196059232737294807483749405530407650*z1-208927666790220932385400001705796589143660057311594986871284248063452764123684012160137778676211085552953803731229362536931772968254876379900127550234314747382635298353*z2+212890944902865974203001830409897499596639241861782129799604979473686554912635688401191052889115989522800011782344120805955475878176989638316330052196457197857848770789*z3-9018115470197334200227416766352969636107018644707202303884988646767253560378460425239535297591392226916731753986357167185842049926065971175582157456425663519685515552*z4+32807596892202252111852031884232082774821529791857099679117561184491574998255058387392196320965547938012176216368288737443062734872634837437315261282649191409215162676*z5-32824781525525927251538391645210298177942796865694781207050247580809264078529951028509334979006776745851994181348764406547584588582964446284379972095956567516257668650*z6-298262730132422225015166927734027078700113915173355167571899118915937428457148087998019020504978613749340647035437552717902879175157939643948368582724356149397254910689341831966295059*z7+45379900022553035328085945453194822714953037853601383296526110631743232417657781055211996885318263671388165725939124638099691960510303608202496025984950635643586613186235267840*z8-1269619003991153921613167671925482567915110005750757350619588288876717852108067434342269396624514079043786993393939076404257165759201245949718745839855281930773162245408622, 48974972356219876752502441469941341381875233261366248698285095660282059623514037376890865531341815847750185309792229443124438110680272821986627407036109412722255068715952420512063403056083708248940825788379498012421530809600000*z7^3+4131881019632411438214016018914114863680009944024846365639020171372705694414079252870549314526697827727431601790559952176203720555083691579215964887813324887757880383221566958066608436433037273097408289824682016743752056832000000*z8^3+44705575815781217538348476677733289313528693230790769903498578154886197916632829063689017496846559804447728627524742618388491771153387425549772119128928010644713914906202702766329292344681179349663090016*z1*z2-8405065031031642413077918827135802957468607211954018981239801813772233047761851503817056761933038076693642617125793827031952017605261708642031111102362029649558997466485556999160733254875728451804571560*z2*z3+1201791724808222775235341360910182011320266253113473303766075910409948618567661853926094364186337171605001796457150773156893550653077930903398756870450171184998345485510031547758248354572715803033091096824*z1*z4-200271822287595620497804796462800241676133901556037895193685153686249989069272581890276756405875596264766921775498805471539773813226604695753619243762149293312848660429385050332956607649381791972284808644*z2*z4-600830261572587964761633581248269701234616772752925288236867206392646040958429634981091792625402258752795985282180734592585810512158602336329962049553916768499174604535249437675026258049204376260421641196*z3*z4-15670052724048306479334378621075499987301403164938399649906184684881246270619014603904403431779467022225129948711226886247511844034154657856104356000864170681383561168752506323706837302874233332015467830241296*z5*z6+15672850855765461951051950585254702364137140103306628679468669286143307231006217007797514501186242544614176578137948541860262698539996435137317438799477865925798497538677371527163811838773259243730045759604003*z6^2+1239201231366104074846460775806262010987830919841579379735264965500488217344179525952649339966350436190332687142634612679019593927795756348938042917637706807982511312914304538972336003153293309531660845626185749622*z1*z7+619504469999771497982640018019944195246864849257548086173795566922015169649520993254645627358694529232895395411850229065687661079437461451233541274043006927359894124426642187804421659189420053491905122944201931915*z2*z7-620857382963052394728483736919060309449012483939411911010874574866134510231092870305530247959655100951742664335010007889689025010167862021420083629817166029282235959689051739268274275150193584540409266511792213031*z3*z7-48700039499688091738466732755830639671687864880092813765402930622649325701330363152633924349605846456131006924194759878721605823454885272804226624227117003466230518793813958938178227361632824677767599892445402394233939218698000*z7^2+1845303967415926144043095796878661040264031797577200415688158037543668812839019621120935042952270775420783034215715946147352953401962501242258155745643995160405159212219919743608700157865315190524581346513864290304*z1*z8+921569952262592512380879094423206153475263345323690384844303271504370411623097642121822515166607238256614143707956465023532862596518159324181610653146079197520369805566771288313845183281637717699762780183055620096*z2*z8-924521552015289973038208470147305030973215603570400155910951156794804405176440477290546387644410246968923398971415332059653706868700628322538399656672046784005553439975918814987623764073384227895303795614136686592*z3*z8+1008343987900385502067437421043648602577316577207243560403299999005172410026604845819121814143264327332237129380925460644241612259682889626320811628390902232985420191286099978346117403886489977424781834404760031919027744755712*z7*z8+199473619005349372469179836491374283613667131171620819926430517546980603292842797793701392447913506976381006164902365824516278519173350831747467047253408768667079590769041877760728369955032704095916303924964038051095367171955200000*z8^2-136319804383580007180744044920152046762024807629893474087905203311214133694671209879459557034881890783664274099262479059002328766160335416094728780286599482050883588580939604903720977994009307126226890938543290*z1-68024727695351448148440825367325767869713267627339640154903285738637620850616288988634070486623397716864823893711273204849280313293311834938605151293752659089775259509381049449911947815080990142995223232831133*z2+68329665433761815422005002197437066821689688758061528626960438676761299060207458604784369563475751744860242105096708241922325938914537977975611125362504481379102188281185425073394029626571990665729137574691169*z3-3542844059659042164808058885509724691402150007316620124976548279374073060577230809915996814106709892182292330444871409037943590461986603822778316007347243785914336728827989148331867150122505028508420394310992*z4+15670052724048306479334378621075499987301403164938399649906184684881246270619014603904403431779467022225129948711226886247511844034154657856104356000864170681383561168752506323706837302874233332015467830241296*z5-15675648987482617422769522549433904740972877041674857709031153887405368191393419411690625570593018067003223207564670197473013553045838212418530521598091561170213433908602236730620786374672285155444623688966710*z6+48699614072178152936927096530049784496977451720573072170998817921280086524550871819719299894507985710648970406338072100563931941792243701916488329277890503141338377746925486463488959183303600380427868835815559394015187310327601*z7+17136635961182543634512185577730212442241091224702878192894593440232050340019583193198317587751477028013534357286128588773963985187311805412608097562798201931611459216719483699073366816295936563355354004418322177744640*z8-413213106594329542400823703143053538418673919350603718745729214438392328395516647908533890073042333817896763973647103655193900422792534641051604919089295728372209367312429288695183252169316009340158647133384601402, 14798194475516474896137648384*z5*z7^2+147938544*z2*z5-121676*z3*z5+333321424102754287200*z5*z7-14798194475516474896137648384*z7^2-147938544*z2+121676*z3+3376328606805*z5-333321424102754287200*z7-3376328606805, 160910433986011706731308631269904138846195216585930483040296690481898279494458511362298619992607777341195583604205471133020544085909368943443959926795883661479929459897156431360*z3*z7^2+44228273996654755073126220944268892198463222938475460253608104670547411912094877711492133526778340758386571532836572713109124011579598270041543323917420492170983659403684144539850457088000000*z8^3-3066992517541460226343012436682496155837964366035286458319776660977785276631330463086737830795702710704223690087984353383616226123510322209337387288591967937718114016*z1*z2+1272392058135508057499969634877693634426106927091186858770085912054070902190338223189717387131370578860827230663346358688572649673165031480297831697667399226941315400*z2*z3+25718011310808383970671312107029495321954719259892019945097480827136024896877486190467738968009759214505893766657710307084190025332091274243623356237119128732578716456*z1*z4-4300391838332344104853491046894577008380626384552234810995094502230743346321239643084875402420339501245718573426508005069441157508719126767197547826790583788779250476*z2*z4-12868942556687314152109826862770369610500908047438194058149478976019113015304585570458734178148016540742864387305006147315150281206080127308059165186026171455924601444*z3*z4-198223339587327691884195792634891024284684134814447161210418770498021389808507343200406132670740662320945748667723078438146565766144105382220972085889403339461721984876384*z5*z6+198306716380499919786087184180716693658487948137300220930904947271674886058643654274477014239796361219389238659103951024210548341293865248048583405951439186186823277603697*z6^2+33168138262790571533089371453721130379747039624010079336602967060147684787995223531335513798204130547981590143096628861770202765953439504351992260310853342335404211330387449458*z1*z7+16480510232907025922433656873568331874432555828870477594837852361827320843049980915178345023271320646684680700614136515662693264612489293767118633304612747195224807955139108905*z2*z7-16495161168753754897391228725423326943780268798684558666790571754403724872666929218449881772549739904666288452627441321585608936116167473441645898717257667028847227612448149789*z3*z7+1964096436850215940348477728624288192776905807224351337106277475072081358299187576999797951662447234062880435632892760136183598743007454231406532117798937133965737681326883506295777510480*z7^2+49446657337961465966557507245931857292789370151772266078779629993428636694469345758988704290070476655859510342212392459890234492963727294311529483789999444578861163543573139456*z1*z8+24506956360441943953566916897034302849274003487970084866365456024630342616296432754718474429287275646939293323728707687845589573678116634381550263999287489330536567226995042304*z2*z8-24655879851993248245204845177228722243580278217420077991967347730468047304267690635473926561185309588583615809110856528486891447953658615709404775674059666664999475964112037888*z3*z8+10790755714781567941587653069165285194690489139963135896974536233476402793826274024446227418512545037046217721951634343559610588142627362647369100237039823534474346411039601795244668448768*z7*z8-8069489164208819309208440321805654499037076073153302017346891968458059270498397752009108828404076575139446912291969193479154958989358820456665805453974928651187760229740702232537021760000000*z8^2-4095431968588540599413039139548122846193920062971861537594299826740908160307797106573760220166363012511116488500491467297113055439372034696828435063273932795483243358813790*z1-2027558931576855209338994585577432614574835017668367475641876361152840673149672754693288216906951840389886726141623422868363754268061442898542600456948482803776596455153007*z2+2044537692876674110148984936318995085964361623095059157383494270714000156450508687423148706597929951299080630042282352320319234703061665388822422475748563060292774298507931*z3-77053092126697216721444903145337765616856365966966006535264377617090842485175939664878809282971441824821082323895176817581207949826398469467709718801681401062109464787888*z4+198223339587327691884195792634891024284684134814447161210418770498021389808507343200406132670740662320945748667723078438146565766144105382220972085889403339461721984876384*z5-198390093173672147687978575726542363032291761460153280651391124045328382308779965348547895808852060117832728650484823610274530916443625113876194726013475032911924570331010*z6-1970088974621422654013921690481902254646580843314604549162992267073222616497111545593305266968410746695952954796755691928725224831971258675692582329992927524505326307602999077263332963981*z7+396706879708530626975564250375123599832353721756931453363870457119214549672881217258103448119229482159927460388481792094485064395024367687871137428647422780028145762777955754272000*z8-12323559497314784265672382664391473166815476515047945001248964582597605392475581329005413988686054136315198550072551681193674342301600892305622289070358810165155070499299689318, 338261365511202282251924408046208504546238816865243420720194986651527171028811127700983724737471816960648056669916545607324912004325477570362760584627760672605754335666839772698182400*z2*z7^2+21411832270486545045270897216756631011292678857129226922947209284236192989447296030177842124141639362255036103557394713442133563627257001656611956872627064026948136729280975445018286463123456000000*z8^3+4134846984148723778157639524172637686207978745579946120164248395800686251185592751079370930419878683145416006944147222422886429965378090498046382512809336348533313709004096*z1*z2-1806149331982784637428396550300781318263029365001065892774990552378879847810244694324471974858016946611763151861977925874619322508727208434492341291053567728555075490767360*z2*z3+11449494084021890200071471210735165742098016543053324231647670643972645312513183419569179409746178315079205323166192569764676835824404181195150584782451161011920885402570944*z1*z4-1896534980266694681960058377546620663838329452338399788850035171832874930198853344766299334681854177078061282635644357127494508743893293632628539442754409419345424509775264*z2*z4-5722305014295757084192992357144830404696836457809281439994513446106144701700809381258285909828261381806352819671936592110929503965852092910560532326556526799965331453228576*z3*z4-101420389072023812496733221416893656676486628745798387236557751969890461045622672362329428910074892504724257071614656344361228056428368612067038570048245421516975898732012718101*z5*z6+101455284184339628109288203471068971072209899470043618295519063287035301114705575202218683734195660111834659492258464639315212697854788506712552178703339340413918557537112948468*z6^2+13752466087243753997538033689995617282467678672612067211766023817122827880670972375885021767742673181035604523860774063857666050805226431360679678618869164605020346764647328333219432*z1*z7+7168103553336649019391840619495568108835775977173606214659495609388712686644254055238757745794266165647414392697266474614060419192062024059233529119759521580819050921509976319402340*z2*z7-6899758682803923990244207650797293016472495124015034590763208895925816661932663769904452034501643608099503708911576411598730791823077758716179667783165530882149699841426493197305636*z3*z7+986787874359370457150771433079222382536205888953076082278996810945625040704042304694011468043456067459848257520972107749902805852912470323632631215063540574840242144103728120936930653948040000*z7^2+20484583870104313300176387812872408779682457700708671810278056233713862019793775241082919350762767067352050300927023498232487638044648163132528698276891532353648688182363918527617024*z1*z8+10526340551568107596928256146859583255097081431760395505748598543575963948206395240442620911487298593157212128620625921064694024693931536728188670056947324311890848357436314095922176*z2*z8-10277348124843832520058950590620103289783771523888465501493962749211543327517295487476284449277471996474072714398637019190427605681980139792404989331434744882572906651856329735089152*z3*z8+5224225001728948808652492610364659975406965611400611589520558888559128767624719558194003586951362751090451006653568098231130901988965117890481676298554849505461034436494258794750201336712937472*z7*z8-4053402293317719315781786349350688601695927218413375355693620022389308332924498162960069116092669572823366879345618521513498510193765572732967602774307708434674988663754714604744094109224396800000*z8^2-1657319223686637557758770654465727789159343032664994250197124850324935877427203141660174549135136552662833207464022368484059563711521185727499265924901004365731083751511873911640*z1-848536902546875130444099589522332818332730288218583180752797004646923332660320866699816110070480035006641460436347006545442378124110143043659521897051239062606372342737744466748*z2+831842594118443029985459962439471487772970343659624067928953791879068501389938780530870040250939446995968525531441699824919523757025890318354957542269759071877915536332723893564*z3-33839517926699771424733856415036146120936043209790108961979340046248324734672491772356400981769571628425002264912524649124253526269824619897296959187553346841581637983063033652*z4+101420389072023812496733221416893656676486628745798387236557751969890461045622672362329428910074892504724257071614656344361228056428368612067038570048245421516975898732012718101*z5-101490179296655443721843185525244285467933170194288849354480374604180141183788478042107938558316427718945061912902272934269197339281208401358065787358433259310861216342213178835*z6-989599654364107965191173959564130644950699394805068289263235189449691780038095794056736335333041302062277071824971064569565660678236515389659076154295375882199167867248665462211412633666207044*z7+173236853815191917027080182628940521626480662632167281273563251059013404052708667360891681609339829191947600999660679132666135510522437761985131081626798699904329365642324511002973680640*z8-5156972002306517701935856897724468486021326731893256651436664243795012543138060543805840088464084103400605306418758524705100272524638523539128153142073207186257827983387175686556237, 2891598061249797579664650537301141252080292368402541160192362207114813890103267900781054362378519559749087448107128122896744274901352101538527626237159880811359399219903940190745600*z1*z7^2+305717922497682237414371427384121008147029839194918739200934011981637727916110768276694294482277492996209171235993921179991902431273548677364609311593851781753753626286717554625685443559424000000*z8^3-45222847797457073656629780831075800971498367673620253956540384158212007180500413641851481058258947946501346771724577299273611709022470332711767867349866483043562366012192*z1*z2+19148119055658438448276163661102308963427818960482280169725748687441954904210820400376517745311808956422626518801943022993396285858312036951075402698025740178606515866520*z2*z3+181799345618494372099745469097040143765720941696491615624173337587581389514315564810398990592333630522088263894726919237113437395907670966486325231927600889962082348022712*z1*z4-30476206046878543846196914539050150966517870386046823204492989352258916779831080991225330335532391807263806749596331487016610705368397686855707807643253677234597625539172*z2*z4-90999364455477872747997985930658352854497096505946752524872517255992198835031285932041410871760816321430597946588032782612829252595586907226061788801966745407549231881548*z3*z4-1333734485526727078615073259213142008800496301704368676510674069078330711854199676797473075422076903048540899416261894175040566372122615911706100854236454113872153353662940298*z5*z6+1334334679579302449872337409046387826993438360079677204261777219149725427812621373024454328395077718151264484902026937525576462338488474397290994815834380481826863573015815539*z6^2+240275432301755513214653371004976686044446703694489109935632962358049579296719906445969990357101654849718857593585334273317388856148926487782020999462516813839411688000392942065686*z1*z7+117960133952755838198261926019778570051167695672924056273422833739210740625818356054262686600579440665182418390887929836228580868493757083716369865390482482092451600264232238231995*z2*z7-119238268458955585083774938873066343009873412960262490120059695114015381841228712858172168716052804701916710141762594146578568939458892463531012858146147138390791299864113522890103*z3*z7+13423129120726753315587700299695094279035915327069049194920786349928660177998270816190025057612672500299703219844276361780199365388456846763645445550996225556810829976999589062377667375030000*z7^2+357107718654747979702833832222283602379993542354482451633447505987250230841259455292052868269118045623372151053747951493079069162761357953252515501874765106917733034386150750871552*z1*z8+175396402773169762289071573317573718674575067822942157626045978180624212256904932230171127808786346618408341520121390424518286262181873160319431342072020948577914960664901657448448*z2*z8-177797917962892619069750464946150690087300493609221290783667160653981275482814699516697967131924237863475537388305261460015122429173383184399074657369932752352413308459005034090496*z3*z8+74587834055834375602574521649999952604545721672030305435938831566883742026464072473874979778163183945432859184483320680687267635800151587620420521493100342593478673900236633390726007487942656*z7*z8-55152379386539560977195149947810104595111622826966388338446112780360450225372154704165349787196623444799969263545589643530000906150967524584872221080274907669874963862687317315333144069670400000*z8^2-29723419790119057339086604355878548634306496932969524463369052127110764746857953653947282272796384356843693012422408642359995752682040127378197828093905855162966824909223674970*z1-14595732452411504722890658899435636317734801270176109113576145762487924922044640988934217325010634824364194621248796315323437481839633871797564850490744081937601551839846998029*z2+14819541606880507919251925477427339910062783687232217995441870384059708925414802069474179078558219675178353007761393088913773816826596258522446832234598452236878205984118459697*z3-546562637020933694665065013761617911208216047593134738260625120960809590732213467541885300108783542035071995686846078678870079540610032602323206727809731336215275172036136696*z4+1333734485526727078615073259213142008800496301704368676510674069078330711854199676797473075422076903048540899416261894175040566372122615911706100854236454113872153353662940298*z5-1334934873631877821129601558879633645186380418454985732012880369221120143771043069251435581368078533253988070387791980876112358304854332882875888777432306849781573792368690780*z6-13464928217929298949895049034464115400723130619171796327390154906325798308682063998847528203698127293616611663696188874901421898834128333614401932114081692444685144790452903322030862371112487*z7+2821875350647788845680955790223176315489127613375623085267730387743191015899710902700455630913304928671414109380756746786495824127510091260485844867376104008402143184136366565539557120*z8-88715411877098217804649297246598507003025563659266763049796929654408089520497928609223153993387262130501416127641613956313419778867880923842216803127498901969295457370420417783676, 69944154198163700498458405179728227420894125180108484551917525218063155621220271835812000142851397409891586457383777425642775661933826397772999761494356576204990*z6^2*z7+20609901425945492675120725867251590836652228673618910426910913461865102138655432283858055516597142424828820666123335797515169829910208309505219795843678278868715413579366400000*z8^3-722760188285680057867355919135377851195939673663095733859787642709635832795173647949347917511748275691475056137662020498327825912977103806374143344416*z1*z2+323234654611796900796688405773733007100255361737306139252163131507476788727700476207645906190890283196708173538817969505459279383644927340260631931800*z2*z3+25830406694363998387347753848575040794083075347028106387561285319497683187818566875459652775969893086461268371550278845489067312491345549800704156992696*z1*z4-4309634238353982021889562970756666950351325405311828195941992405725051495495980821682739389609811657229299733702388934345407070483318669186151418179556*z2*z4-12918576101019146904936404357992519077694909165852139546769191784087331147867487058872021590174898931122665947031289923808533905673913838515568198153164*z3*z4+2610644875710162309499935870754276565546349548441245029851583773682360198335889809876768942372833217009910580951958413425990011025253487440115363288556261066*z5*z6-2610703164999000951736212935307513256891401192630589205734793138461249103625001067782207221180049154916307688823125985060368842142074351093553586533879369063*z6^2+80336796644801075279926773816373194918637397825650981747123383399186911475018556744212002622243257817854353972603652109122162466019961161809262151377493628818838*z1*z7+40131679334780520390422971461762419761568846182467597336456202629873104726568816403099009191609338051700317061138372206019480747877413956919891962420534156855835*z2*z7-40164929591497782220330813862408602044341041873369263674218280352320883967965879952402707640578142927279147694974027435667679896822646970834858961221646310945079*z3*z7-139888308396327400996916810359456454841788250360216969103835050436126311242440543671624000285702794819783172914767554851285551323867652795545999522988713152409980*z6*z7+831051075366444389441557014335878939082513974886616081101024035292738963793635659039173094342685503045639000921886982326558660539429614828911525268367064274492769319046000*z7^2-88600888288787735126350927262215835124117878287411816638041662632403433721719399053630977789143828880843098622918096853840779338863155887499424869943667328753664*z1*z8-44361712575340206399588056310241515059136016945874195891732439904547547674038173534613006135776639782014302386431567692098459284512963472736860127245703566667776*z2*z8+44305578043217609337272756226847559830959675629555983641152292566799758786660868951798713187680420350463416387170837128640701378842175210159529401503752362831872*z3*z8+5026717824810429963648321409399699898794321079445228420829833082495396200228816799402980983071626239101067152739126834157042434320121965395964513062729270465468250512112128*z7*z8-3417381951238696752224885060931040804713843446706890185987329484929740546111060323868223824453550637064319543752575778637371110658750272268777832086057300253748555873113600000*z8^2+2822674682740481378140023539023535008250567151963036084522113383158779433872431078128198517658219380106956445304567054101294299582201074401339131980241959670*z1+1419302367766394939929531322328327276129290317640041896262314176757458189030424671392702563376200584169223166984742976562372945606484369771739597230940488123*z2-1411801455311692346504562481616594819958251060689728008187051665051374314437853693732419291639111729679497309538066549663655272680046822111439411436573514999*z3-97073936124370820618045547866221400708746894633559572153670522709578472794499774831365000674605695845880659765693875914528766645952642825508793650948829848*z4-2610644875710162309499935870754276565546349548441245029851583773682360198335889809876768942372833217009910580951958413425990011025253487440115363288556261066*z5+2610761454287839593972489999860749948236452836819933381618002503240138008914112325687645499987265092822704796694293556694747673258895214746991809779202477060*z6-834320096249003694741582214298642971103952291076330845739804375232266591429923304840563827033443407871343158282413266607949290965260054715197429491300770389730477675236191*z7+748147137152907546276618560118924950573224750441338323358334133860497976073843711494048570895696312782606003458065305407818441725928596846524329418569069891534462720*z8-61286027476249036010715932930753352268759478969795167914393205476613695590417560861364606357625728577627056407795700764954677515307054148813575391083478185871638, -104916231297245550747687607769592341131341187770162726827876287827094733431830407753718000214277096114837379686075666138464163492900739596659499642241534864307485*z5*z6*z7-41219802851890985350241451734503181673304457347237820853821826923730204277310864567716111033194284849657641332246671595030339659820416619010439591687356557737430827158732800000*z8^3+1445520376571360115734711838270755702391879347326191467719575285419271665590347295898695835023496551382950112275324040996655651825954207612748286688832*z1*z2-646469309223593801593376811547466014200510723474612278504326263014953577455400952415291812381780566393416347077635939010918558767289854680521263863600*z2*z3-51660813388727996774695507697150081588166150694056212775122570638995366375637133750919305551939786172922536743100557690978134624982691099601408313985392*z1*z4+8619268476707964043779125941513333900702650810623656391883984811450102990991961643365478779219623314458599467404777868690814140966637338372302836359112*z2*z4+25837152202038293809872808715985038155389818331704279093538383568174662295734974117744043180349797862245331894062579847617067811347827677031136396306328*z3*z4-5221289751420324618999871741508553131092699096882490059703167547364720396671779619753537884745666434019821161903916826851980022050506974880230726577112522132*z5*z6+5221406329998001903472425870615026513782802385261178411469586276922498207250002135564414442360098309832615377646251970120737684284148702187107173067758738126*z6^2+119103023503052651433980073086166519846301705069131974713423334073878799534843973854823995326919074003857637884327805484326777715695383267473474743222439047182284*z1*z7+59624949726766360216070867435931615318650557995281774430922645176380101789302910865425981902484118716382538792490810439246589828112824881706215598147644838698310*z2*z7-59558449213331836556255182634639250753106166613478441755398489731484543306508783766818585004546508965224877524819499979950191530222358853876281600545420530519822*z3*z7+104916231297245550747687607769592341131341187770162726827876287827094733431830407753718000214277096114837379686075666138464163492900739596659499642241534864307485*z5*z7+104916231297245550747687607769592341131341187770162726827876287827094733431830407753718000214277096114837379686075666138464163492900739596659499642241534864307485*z6*z7-1662102150732888778883114028671757878165027949773232162202048070585477927587271318078346188685371006091278001843773964653117321078859229657823050536734128548985538638092000*z7^2+177201776577575470252701854524431670248235756574823633276083325264806867443438798107261955578287657761686197245836193707681558677726311774998849739887334657507328*z1*z8+88723425150680412799176112620483030118272033891748391783464879809095095348076347069226012271553279564028604772863135384196918569025926945473720254491407133335552*z2*z8-88611156086435218674545512453695119661919351259111967282304585133599517573321737903597426375360840700926832774341674257281402757684350420319058803007504725663744*z3*z8-10053435264648235220603635275284337688364478434289191850342567191236733600238025059609585781834003691948042961434961806873773917902406687508148532782867853665997905591959296*z7*z8+6834763902477393504449770121862081609427686893413780371974658969859481092222120647736447648907101274128639087505151557274742221317500544537555664172114600507497111746227200000*z8^2-5645349365480962756280047078047070016501134303926072169044226766317558867744862156256397035316438760213912890609134108202588599164402148802678263960483919340*z1-2838604735532789879859062644656654552258580635280083792524628353514916378060849342785405126752401168338446333969485953124745891212968739543479194461880976246*z2+2823602910623384693009124963233189639916502121379456016374103330102748628875707387464838583278223459358994619076133099327310545360093644222878822873147029998*z3+194147872248741641236091095732442801417493789267119144307341045419156945588999549662730001349211391691761319531387751829057533291905285651017587301897659696*z4+5221289751420324618999871741508553131092699096882490059703167547364720396671779619753537884745666434019821161903916826851980022050506974880230726577112522132*z5-5221522908575679187944979999721499896472905673639866763236005006480276017828224651375290999974530185645409593388587113389495346517790429493983619558404954120*z6+1668641302371846205944763938135259334135417296900640049441041620291823343086000007204401144731705082508660416724520438981678772030084312996352138844561756171911106571253702*z7-1111321649599122085009722058128625737421848235891359547742914208920776343608491046803787893005138534221168715054690299864899046208573413199706068149873201187636660480*z8+87599977853416221772202663271642590827071895349536093552827648344195813370224985804823212643825758450308319586899512817087967199647195098740650901419778083640781, 2701506920112*z3*z5*z7+12168*z2*z5+18251*z3*z5-2701506920112*z3*z7+10955511063360864*z5*z7-12168*z2-18251*z3+222017334*z5-10955511063360864*z7-222017334, 2701506920112*z2*z5*z7-6081*z2*z5+2*z3*z5-2701506920112*z2*z7+10955511063360864*z5*z7+6081*z2-2*z3-222017334*z5-10955511063360864*z7+222017334, 839329850377964405981500862156738729050729502161301814623010302616757867454643262029744001714216768918699037488605329107713307943205916773275997137932278914459880*z2*z3*z7+4650116841298359394664381466223082503082937235714009743404177068874110015524526212156934956263241718670449102115000630611148516795555455007860153292082648417727164287693176533811200000*z8^3-464990140328848009213598797906780475477183586668361610182313438638501184604151261447091216244628516762748882603237985443618330052073037427161844492932031875552*z1*z2+216686761945905615682274018723226799223060967212468288226520837913688215785838936321140537704654398399396783502318227921502581486925804574194305019847476869040*z2*z3+2281017651504789159691817630395648928502215540604064596953932398675272258122847659546784158576616135583103963669743887580164100352538714036632792261063944404872*z1*z4-381707740913625639710707819595022581413261776610767724976423254629912764947951844760517320374622926983670838273300927773223927315053166791798105451128889516092*z2*z4-1140983686870531234708510429431207777929600590887075237698665671841782015328535458375264455653010549073265506609631735439033415371663461686147662040583533858708*z3*z4-24259584042790591386645287894375881495729160479172983493685902472489972959609354332719911849478744648555701879188999887262319328233101876974810808459494851004511908*z5*z6+24266110650748570282455636883420708136338886950692810491837610218317834768770049997693838931806533814110384031278140388521890886179770158106287238750752070464722989*z6^2+2754398885431197024310887332963553524693306728647749740507750618455086910426528033490628033616967258056960573281817215282185086665336248979893443908753688330532649947146*z1*z7+1353489958221295584744359953456245183758253874283711512373083208883832985744872734586231535969240451610186693837158593288502880552359886937184548911293831363911321710245*z2*z7-1375754492197103544327678063665422110386310429774129246019541142432084129641523689562034979154889529172541207556974094327012703473215824549256324296890411987178337542473*z3*z7+220880059589925345704720909660089927673499202049556408931135611656538194220963890893412417394348387262255433804524162700838774306127940705490899614757489476808505451506155724042000*z7^2+4098593094572239786483994546658326734704353073851115653874636977645725378916147891179890041909372870585915528064339683943101247399660281885946240213273940693311062167552*z1*z8+2013937251981787781611140662393005576322068498810834681453530446132533163218445637047471089781893661286772823044107890089288693168645940929408503503210620326273958033408*z2*z8-2047163216562199687130621432686583432770263101886515640552030897713131067874875958325966433627296045830538056839284040305569636733640574916961672774262651346185298794496*z3*z8+1134606259157273112643302686802068131296030845859675015149096784816481579274657818832364907360657289370429798645021602429663207855387021759521038362172354804224677460036745642356736*z7*z8-907160943796226250837409772124155823736630679311736178761408748385780820740361661814838804399268983967667963015908312271281067137964078181663694359948795713837471553104375497177600000*z8^2-323523324321394574634377502776002384395739036083922001757488314279261193413474898859352596580864936721727348813175504816484548949336663998013833958420146884980314150*z1-158699804222434367057303443560148192473702543535106115666666553068212956156862470855876610094182925936418803129035094138626815585590958301443190371259517466544172819*z2+161568884005001019258728551979346216563993205967322256794986981238195347813247970256197451984873619229288105596282423574442562591374591193318528725953956358751433007*z3-6792549738906569180415884958659818126461497443092160965060504940578080054999733806656440025586683248050083783539576915164255043590674069501528116520617186865158016*z4+24259584042790591386645287894375881495729160479172983493685902472489972959609354332719911849478744648555701879188999887262319328233101876974810808459494851004511908*z5-24272637258706549178265985872465534776948613422212637489989317964145696577930745662667766014134322979665066183367280889781462444126438439237763669042009289924934070*z6-221474735736865387594891250507847630995502536400050780694201277969156428048667485636435983552933015954021772780241576336492743116827119783103473921557643863070539989208627649680217*z7+34229986928695544595032356126378410737153197044078840169510848908372172104994557912131278656772437470286465695722954441540835517509215498396986636914080065640595763315626240*z8-964406279953336795678209069877146233745954614095445668121131376568591418500990315167609217271967219095351652572201212508002068951454605343598525911105790997099967741906, 1678659700755928811963001724313477458101459004322603629246020605233515734909286524059488003428433537837398074977210658215426615886411833546551994275864557828919760*z1*z2*z7+5578004211713768076516015287570349324875278981530476407929959912401842271785028559074591465874344741640456575792081415007797292128306381537373143141882938748504501170131939056025600000*z8^3-575440381944559108673648522133937602895262217615587393370756178397836367513608883627900248024357907035425146340797318849932622596197365500332421262843200860944*z1*z2+283077803123368806296675004446359553954018692896069466761713131618588611458446888007432076395125969820267000254621191577930571290458574234341256206076709041560*z2*z3+2775324896251465032678601510085516213051220704901747739822093943342092133879053297308174548836183585917555105978062232757145223026882014251265989702762213298424*z1*z4-464371621989055840595494612890869464098332537577297628447750301119229573095062913537684753420433995401825442790663318458395115487712457768756678902360447875524*z2*z4-1388033906063472423454409236920082899187971374312258823656522573672218744176195192968817956241104849972974277273751938712633700610870404857167773451552277436076*z3*z4-28784984636714765940949914770976444178690229044652030770794531118365726496949564632573484445529863630406837856035279489892003333679833554460424281407732559895033666*z5*z6+28793020181975846157276093978374274949241952464028940077629369572771169728698491217309195972778991748283568402664648321956289671951982085153282735679599690073103643*z6^2+3377173317693101698085097345636231442900322318773054458234749983121858513339274071634439763511317302203852079179129995214469996320148993186895226380080363324401522976422*z1*z7+1658559029442436842486545634162621675466705901386081494339353242679268804400414595897843578160175212802972949952882429641832197417672086608302913251295514851794491879075*z2*z7-1688144510506390695690212188364138222128848502623069896306199109681466798401636386705654655041814199832667038613171693594720716268811511890076386018626647977372478188671*z3*z7+263628260807994171966137581160945810393523647371014575335873787501896017023218766979573031579201470856536978915551805838441160897880370484466828947353157950738248401046115638534000*z7^2+5026181320616511567195259650307534070269211609102075267676886985093071552231698877052888765605629608804941283904073904650625042064566553898477992156370356910219776794624*z1*z8+2467713436218557029950331064708045085444508292633414762084682518017762046008774675674744947541391454104680259358552519075980161460779522119813011351731228633133236432896*z2*z8-2512449170472342187163615602155155025828658540690583400778788197094720523755642002301414767830177973832592099126573732228451986541487968074463922373980852995601325309952*z3*z8+1360999242318891634204202117941140638315989307309015320546601635260106255990636470625786192771527413526424025483112000891646896959627213638155914612398292073712780842498875990003712*z7*z8-1082757074144509218567151002488822066877393708996130452182397057687654962358800598381918879364203303041313733947686339491856052192626116117532098073604202543405591260886669970265600000*z8^2-398706859831696028409158229196398592359783452308399844600882737845098142565601811304720161017211488137972811514549115492439122706234335300572768922407408957788645450*z1-195392756334347906773721671924479113296667382256623806232120175418583323797886617599946967438209993934054832777954902029035156299770658783076330424808804782649471973*z2+199296394091334211214615167429498582416007273449085651519906933311436257458754312894798215824679825290301037697216311814005788471540888926342602532118527884950077689*z3-8268678452132448363642108977956879620922225895994068001072570407542727837314932817699411155176440263157681129165116440018008342380727180792270099254217008492634712*z4+28784984636714765940949914770976444178690229044652030770794531118365726496949564632573484445529863630406837856035279489892003333679833554460424281407732559895033666*z5-28801055727236926373602273185772105719793675883405849384464208027176612960447417802044907500028119866160298949294017154020576010224130615846141189951466820251173620*z6-264344862396695300983719108231203113367979448949094825923476704522698013218620341471994490833543703271953931182950521061069344110479846116959002483397966093860023839155072303210479*z7+41750297099399914476784940265372805431010085062990649599634211399492199644016681210409493945525154036248042997992658439962505107476734186719952589397993052337572087822677760*z8-1187408980536390097217198307081049681161528138597737408870534102211149374578059079883419349043898841140197466345977742310059118651290016391328581129308691533963708268772, 179964720*z6^3+2663118121248*z1*z6*z7+1331559060624*z2*z6*z7-1331559060624*z3*z6*z7+3962639056896*z1*z6*z8+1981319528448*z2*z6*z8-1981319528448*z3*z6*z8-3664450534837248*z5*z7*z8+3664450534837248*z6*z7*z8-5839495234560*z2*z5-959811840*z3*z5-38692189136*z4*z5+7739529408*z4*z6-539894160*z6^2-2663118121248*z1*z7-1331559060624*z2*z7+1331559060624*z3*z7-1314403648343607920970924*z5*z7+2463051372389244*z6*z7-3962639056896*z1*z8-1981319528448*z2*z8+1981319528448*z3*z8+4726437481664512*z5*z8+7329891930356736*z6*z8+5839495234560*z2+959811840*z3+30952659728*z4-53289331923056437*z5-568823537412*z6+1314403645880556548581680*z7-12056329412021248*z8+53289901106523289, -3*z5*z6^2+97344*z2*z5+16*z3*z5+516*z4*z5+6*z5*z6+3*z6^2+21911022126721728*z5*z7-97344*z2-16*z3-516*z4+888339132*z5-6*z6-21911022126721728*z7-888339132, -8898220800358103909567193558367792245853394623504925549504300545493241691457016831183183450126065350962539105525155116279998087169096257704849082083601576262765*z4*z6^2+417812877310819811017298323539570345844436862562211414135641385389918020211118997895533253536377855932390790996619331875365891004204423317991045416591547347445025643990400823109222400000*z8^3-25074344555638653187104398150875623208730378800526833277469536376084209383497358351739755201786601651222954541940287667343870988384253490907775290262555823298016*z1*z2+10593657853296282873659774617720148499988382412939811329814642608658726393616860011079233842992208746251906346278393186622202203384199149404256388234228091139560*z2*z3+433360000880356480317002586769100932296128928234505471051670724954410114360772490903486512184455290974515480298572247306827376538395665293917218024798511276489197256*z1*z4+216455244438441500120619813824763048993691897544278306737362363018298775289624293132439375318370284746147616731493119160105657609816031323973934915419294518554584484*z2*z4-216680064928777497330303335346889871233577116772927874357986423724524224376095295362166527882952926030831993257928063540402384267460572222398377179512848286063533044*z3*z4+17796441600716207819134387116735584491706789247009851099008601090986483382914033662366366900252130701925078211050310232559996174338192515409698164167203152525530*z4*z6-17922367299239238632283947172095167363809074291881867325649021251443854953886845281577207344661962492431502429841927026132820230836728103258795510002543159395012199859*z5*z6+17923779308796638039516576809666219361379988130550732041327828868137984367092953275358041204672087747994991852932795416114972935548105251082189633537032439933848851057*z6^2+775806358406623626798978474512691726022951157684626979388108986075540348201152692562154741468859222891784292784484352315471711247066238284197234155897214695463252426965818*z1*z7+386829194298342094537197587226391898545101712149377826336449196645894992859141880296342546614352371471168862504756854982832194204421747959549663183892086977173952221984845*z2*z7-387727092534179610363521986263967094354484868766304787998903231537079162292437576895259360482341369185812588587481203349971539629499388533181336156273075778401537019609009*z3*z7+18108198613180681440008677609840545482313705082039825438674229291467765891317760437849358638763751113688333543219428925976023525181830800915823727712541342675046137296451697931066000*z7^2+1359395845959249129973471739110437790378419698842503360053844609946985775576497638016161805617091239116818239442762229402685640148660352613135749111388597630906117622831616*z1*z8+678072004030826571790531577333558577740517905339146065833690548954967804781075339582239685903330207225038287532820604147025790680187088587581817552334920342671029605854464*z2*z8-679436788327726617552273065782613888895735812688853234650201554641186412452367305581214573685475456817879194932708855366846424910673182733076427727642713076949323571981568*z3*z8+101925751646301993867408693440170383425140574636897525528916072524198860317728440152353479370536110984130896671883508465807127801982079349579690796120259720752833704364508068714754048*z7*z8-74417397533469092976851159532000984568754821474917968029106936860761391173779790930211001739808707232789592498804698572480343387658348523894363580720583337732513325670473226657548800000*z8^2-143549481548669038921248920205057138360825906308547467487739038355215030140097923581239910640797480793905609711645182739579485530528075714839826856364332060981166216150*z1-71588915741242635156187132740535349270609001313571670454731351882693444596455598742126734799580891837360012401109105803320342533000269800931455629786649466093800002347*z2+71751081451788490242385470580321732898118160607233092247100443850622273745371804630952905715924295518699037595850875594210024016221455346398596142463529794732592903911*z3+1316572840801580648530512558510137081407335348168408236757505231941847852486389758890920593926856032164974160101345501559123795030459682592845609895182565463615499601537*z4+17922367299239238632283947172095167363809074291881867325649021251443854953886845281577207344661962492431502429841927026132820230836728103258795510002543159395012199859*z5-17925191318354037446749206447237271358950901969219596757006636484832113780299061269138875064682213003558481276023663806097125640259482398905583757071521720472685502255*z6-18168294772759683513678169985476388842820940948622918545539987206830025370510221180192318388708262616616444292142152768938615948228302964410688092931023469205027233196374167739020641*z7+7365490431932384897595035914692806746732130325707136402900057950285719548744518377103408964708488197180214821316675837113780460472474783175445304240185161166106000350596118080*z8-435451080227330988964014130270781573558343092155871852323345753759820223721902712070241373791329255960977689108968457038182869067934316003686405754168901643645569250008353, 6621931758406030816422097531808589578309502975631572501956688778041482188991268339485159776838002121646540729693138691185114855567699540617562107597098847451360*z3*z6^2+4354473886458275154590780202916320785941154572721544307355701375912270100044371435475500260862863021933393918509300532826076058312922582347744693364225742629145222126761576340225572864000000*z8^3-311799192478508478805596284953750730065815497209977320953649202360283683378243034148856685579917053120154770462596304838729163473674952177802454988919021693078611392*z1*z2+40750449541963884184060874693584232402067869732340795988680939738336217249256846889909059983508476453185283320836987537338565077493072418757090809932699986487893560*z2*z3+1861541922063251106759586290196096224143810668869066524030340968462725630796516269859842857667249546751531864718473230282217568418903072291671576161972822559581252312*z1*z4-311890999667863447716126815746419385237754749870018142152550624627576003012472953454235724740427548569924268170894271706438660644623032039585404185397117992213213652*z2*z4-932604047835659185017276796547062143044074374361633565776885155109427654083850525804465086845742203992508068344324788233719772795144010150158240935467744905261505308*z3*z4-13243863516812061632844195063617179156619005951263145003913377556082964377982536678970319553676004243293081459386277382370229711135399081235124215194197694902720*z3*z6-24928275747492956792781803833121066536820678452498751215200125464157084141006657285729739589835780996213179600355295243738833576040785648439091511553073322210215754565168*z5*z6+24932939025684219162141977996870187464425129803926128724129989844139928358929937999323543997303029799798420655660295981363297523202711668468812651714631341296815975943439*z6^2+2095484098566264001468718023689513525208086159677659914387195464309831000454053814716913880216752879678855006391392812539269360427239471667263295048240039724001234491742101646*z1*z7+1022167745989867921871229856590678773616756224997380298530296284426780356992259671893850971698274933424113805914748393258862773602722455488406007313101877211886869316310386775*z2*z7-1044603914603343285589639131891969753371447644649772398676442583294936461904683476270254006447488707342107426733834330825626126639679892322396826878838639763183514676358337923*z3*z7+216134739030740436505965762881190524753127116725164842920528252354658461771319427064879194482333714899252181787160578274952187201034994758453675598080729968908243662278774914345810862000*z7^2+3111882434035115087951160719506788616095492555347963181264922744756194843204453602313241549510161906379986167339273148587654668308489967973546067393034001447708097209821294592*z1*z8+1521988084928417832085175943838456989948232070345127839361348146605329650874711149287425932296320704063563781972979794628228903696830934572122213948335998444133490383875790848*z2*z8-1551295374135282172619901058892804015240284306411792716228035299656051159145337495351668174313044929343317061108629947133729283155205648090912799885463345940925478612368316416*z3*z8+1062520531615929894016585895452491682622670986480286476480957730434971071485340955698372142568028684168005974414940093255079952569103914973552674102885782399849914335338620376527441268736*z7*z8-887475475482271555269394991916613770815362934075069630151488771415154433610379870515156218832336437969490621266121187789066563818203120087464969505366339840009652886542617987761146150400000*z8^2-232382017066282425903549641566563009423712593688744669343817771349361990066336477477226563729435817488510476438012973418320646015187768004730340101119277232566712390758050*z1-113379004300838468739345861374705113203271218642510630786415568517166299646052950140319197384676310561449040346912462615363819055993621698576507069926043556300379623846929*z2+115769720999412336574312502798485527233881720438582778579756409448132671275539649069666198809770045596856072132077087475143203163048663124722543155758094630941868292758437*z3-5514313607265162217504369584890800812717330398418901999038864538995484080162015696899981432757322754370937395060023521199965562368865695276704700195911669802376230771856*z4+24928275747492956792781803833121066536820678452498751215200125464157084141006657285729739589835780996213179600355295243738833576040785648439091511553073322210215754565168*z5-24937602303875481531502152160619308392029581155353506233059854224122772576853218712917348404770278603383661710965296718987761470364637688498533791876189360383416197321710*z6-216668730942241666321077686057250095286093488065731905770313381515399057193062496243532405233848836260808587578766262291302128018154663937833720879673723272828906739870970899220971215667*z7+27216685498606200345687602829711350710134020105152194262688795707248835459840117537505584438890516142136719717357312058952902729845271367917032918944107025920342954231775482551040*z8-688843461700880634195392785365894504809334217232307197635982380984027059692606074623940122402760301364274666851279713052082267805320034885985700844472384069242900613978072426, 1103655293067671802737016255301431596384917162605262083659448129673580364831878056580859962806333686941090121615523115197519142594616590102927017932849807908560*z2*z6^2+1084019144170737528821158385336536867383255647448590197050980571624537308507705778763374487620886186470860047879495311361962900129356145029814003289483190815290667099627056091760757964800000*z8^3-129017516126120730084586928446647042195587712819149440040179795765012881384897249575784454654563555720869766644084587115042573052174782349771113587285467352199296176*z1*z2+77549772418355414767010947656275251335832720657295554310477921754758146854797317573296295641972307350561702586740253410303867912150114271789655645164179530635380880*z2*z3+577176633829242436123056034398231078286922842385303212998765953021782644845147226252080351132137546860548775340490514288205689278396738422899259004903120543437400616*z1*z4-96522377463465701253418741055268799187468837598364005023425582223134829824728105260208655551483330185946227819776348607405801067466478248518683748436785048110103916*z2*z4-288467534025037380874182294473092026185182598741726297361430099021893688892382765665185351656020833636731326842382400293186994079504461145398600274061002753206078244*z3*z4-2207310586135343605474032510602863192769834325210524167318896259347160729663756113161719925612667373882180243231046230395038285189233180205854035865699615817120*z2*z6-5338387008209570909408297440107332674124168393667129534872404440788101703694285556487463680227689928862287940349411613405658577549824161316118359792817901736828062248049*z5*z6+5340171600589823356395864934846000230368787326618367290366199343054235579509197574037993508174231749068527437733188560111275126913248868622506438881072628334178899343177*z6^2+721651035657126281450747249167742226900058713378153581632467260006670811857024917223441169394654948884014787131835396240742540849469615941400898024144848535845175826185422858*z1*z7+357068147348457174077510729447075198426335498614959753516148464917854648940915064689552662608877391714523387868789361436494739945595147901535937730368760175156685556341905205*z2*z7-361995155518946447007784894111667099382104247878693097619981003376571945227776319674766070451451925352502572358515397697661547185180822184650926234044433826595907855963884089*z3*z7+49944358574771086653568488695430052558007169987007344096520971029885767509683631441592207206100513351808670531118777630498779928650334498488085679809196550211157487906819195889032906000*z7^2+1074867834928033684286379172278583758891690170295714412510276579527883020899802878260250325436964201759223926662821414036406919907351615974903973201392637211540233261594249216*z1*z8+531128656560262777206931177963977818694033802451015793069274473122448949877274657287887597114803627440830393756169012430128743066813498777965905453212452648443469207199048704*z2*z8-539176873554847346548406170916757438087376471170127986803529785897891348332705703500956728876835283972869889117723348531161121628682070187943978107374379966629323330203706368*z3*z8+264487234407509737660110816683571877717890113807473672356198788432777079068999906370029300903165852280248871440626516075984152627525745280740717707604854297073370327437556007081936826368*z7*z8-205155587200487145830371433153236965040816839441228591912485364965369345249085690403725283323224761581773162371940670609544679568266081695753126249032789180055438048296501109169941516800000*z8^2-86931713061643820193189560920376863624050002060313701565938905874639838663678720264543037429414315681812515266930896959165857138952601182536370635157794934606812084201830*z1-42906191838805141732506560472576023318184228224173935894990818902577022211110633571701741678320537827981543383103645480004217394458900769976031482155356520687300370209267*z2+43624447770634331459773758992821304148689984358901174945305984770391609622532712930998147819031194286639923303592933545509340988492635684188967004464232233078716183867711*z3-1723215876853009380666650886375770948015901392736490005376450112542145439752863639234994786941992749677008834830678360140262404171975211202765687271097214712378997337828*z4+5338387008209570909408297440107332674124168393667129534872404440788101703694285556487463680227689928862287940349411613405658577549824161316118359792817901736828062248049*z5-5341956192970075803383432429584667786613406259569605045859994245320369455324109591588523336120773569274766935116965506816891676276673575928894517969327354931529736438305*z6-50086787182210368479568149763031369700994471902982698605429453615280568858960149916601911588100513815140948480618828692661772098492844726275234056942929971998182264529362451411299558441*z7+8777898868880427978478630269951871900577129187673168455694610366792181842024309520316272910282992394379356284311838449541574911215144995389105889708193746083418995215002700053760*z8-259769329085150392520535272225053505795953187263034891560733568576256606621670258420745660313662174014397823541879132332010998774194999856270507516854785551678464152345805163, 39731590550436184898532585190851537469857017853789435011740132668248893133947610036910958661028012729879244378158832147110689133406197243705372645582593084708160*z1*z6^2+19576663589395923432580521380966929363641791800417357968540976225649470758051816244956545040894247988275782361843624599723376179149394283419504080331113249934557028010225990552423573094400000*z8^3-1710256510596299795387153201277534381543407463053721072160417356895823392816433323401522683209263359464852653486871587810585242811344353170996486494310024462798286688*z1*z2+587894003441999344406061260445443240281265917906660989726083423424956134145316839664760894018978588432919171971876357445922734558227205172948744106675636563283762920*z2*z3+9053933489097369492933237413432916246793970884968211698405003379290869031945049838893827772735610019639226523414557538893903094281459187979783237311039747664841768088*z1*z4-1515851419883617415888399810673161799658858381861069952087506332100541381623213828387220773318100276096804295029871188233473235675321486242370390274675878281388796788*z2*z4-4531742459677282666073292464931505148581924648792650768471599958055314454159103271965850539663188105616401796013609183108225693817851870560129068637494970873790621692*z3*z4-79463181100872369797065170381703074939714035707578870023480265336497786267895220073821917322056025459758488756317664294221378266812394487410745291165186169416320*z1*z6-106554209350657468457591069450917736753515723130796457081968527786506924205011582021137465464448640654076512674691380704702795484204270656235077996102869372678525890246222*z5*z6+106578788760815812632125336391438813820556483054566442283603111210431337012380148157910030802629684674509023579076756944817423618777478339140645102725591302918237192774831*z6^2+10613577582828155940326196091075909617223262374720655388919275227590385031562140739081294979031742849551162546564367509377126690658311484422012251062071739414787197315361809294*z1*z7+5207487077448202477959699958176669701013551481752146248842534747439633621776629499453839304130311292640649204193111881168321272976906930692748557472071690224945835581815860695*z2*z7-5304393985258643067833982317778114247530832097012260084960642964026845510691823516567958738859036696821041096426984406797791592105699569378044036316019365647655649922209029507*z3*z7+948487608933236592782231524843568654731182552064393153799351009477464996125160856239940172324836138986582803342268164957325721770973174152528256607153076089289606400390587112357600238000*z7^2+15780717355095332229400697734270746642244915067381015444756408574333015286731029592002045680911622621416863445419770509582730538548369320451292396860897905904034362740386398208*z1*z8+7750615619088889241098240051468931737944276229900232968672146709517518117767533330417043616117826374934924855487657046233946156715520152606923961738763959022698404517525921792*z2*z8-7886881549687179924446245002216397156092362274961303818795746530679731096324851657091154805256210378405657398685752259785873096150396218539582561750391890785753189589276073984*z3*z8+4776711737028218865937876616252106737623536793632001274919567746913931295449011133111156735143799741539004039356878864459911377317669504551604342325963545670111950352462152903636099764224*z7*z8-3895074038149093440650277375472361305308664488240641134117607342443597927967615681688139299126551732657463567804935744547344548494277953136844927072747345455313040950515146945710482521600000*z8^2-1218882514511485250898435278740257801358964702375203849568944326923011416199371590274598352362587289553761826108740712948051143546143227120179567735417436983345984074843170*z1-597642638785463355292046259103124353833785899021073153841074155120432928041708738092809517657982305518883528755151131982316311921021760592031747978125217197061039614112081*z2+609129185800354024629161805991809932922248167914291694854505123207655336229322277210438695639630408587080905049060215499703075855839101113902290078263996944217144257697093*z3-26903130999147225607644081642672602428622641201794549195331756364318847712565311014718755048082516840877993136266757022520912176618782002013587628243682024829728647692744*z4+106554209350657468457591069450917736753515723130796457081968527786506924205011582021137465464448640654076512674691380704702795484204270656235077996102869372678525890246222*z5-106603368170974156806659603331959890887597242978336427485237694634355749819748714294682596140810728694941534483462133184932051753350686022046212209348313233157948495303440*z6-950945394279710381481813454218791340427097918695265660753254698325319695965606238680703226218077354100342038000481797743719500640635442133835608400659978978064225162493626854914297426803*z7+134430260916471591655767070603678612536095988624083498460871188507193612010022792326744305400508405788792425766222761179726045062869227310664462916818786761602759391345691508366080*z8-3631517845698919420051581308331423469261728295848908109424081488880778928119801092011812305131579555678731686124499437302206146609324871011470364511737350023902966456256955944, -213557299208594493829612645400827013900481470964118213188103213091837800594968403948396402803025568423100938532603722790719954092058310184916377970006437830306360*z4*z5*z6+10027474075964316192677840279509983872225614778843415335433216875353495212857039213178023703721330600676192830650998889625819404677608760356092874051606889698719767414545703052499353600000*z8^3-601783042798684802723049787560015428986039574027287052175224936350843236502227297273376735325641080059951712971590821333684630075274492310599648156244921677456864*z1*z2+254247240026824168093565421216731330666059568746522670277329569558418979402562463531046101121032300559359299412877735960675864280272087534236115503937402189296040*z2*z3+10400639977304672784850663538709178497625035943469458318609035662391157252448739123693684007743970529881137916137787128491875775139534234927590540898679386683590937224*z1*z4+5194925873834324854928883006471699536143279882494720276945360920720371085328344147423253498009857183146493276952198473041384337893686170359479334489272235365196597636*z2*z4-5200321536372994955363235910044846527064385365844854747039125236641743829638414649276777153877508330861587193532716946059847981413300477316710819183431447818673941076*z3*z4+213557299208594493829612645400827013900481470964118213188103213091837800594968403948396402803025568423100938532603722790719954092058310184916377970006437830306360*z4*z5+213557299208594493829612645400827013900481470964118213188103213091837800594968403948396402803025568423100938532603722790719954092058310184916377970006437830306360*z4*z6-430083484799897788799516045531754668874690472870736385696923404961430252692240637966051553565851297715413932072390616619821890075573834784285597906632491679546086268966*z5*z6+430117373128228977825937006973012140926105284907973079755286758003680918877065688053604693769067329592122612402786629145540158332761788510869562497862933205314821286733*z6^2+18619142489825502179944105410700125886809062231076174729961891693049964066136463744017048268122457851235897137762302562104043302443945518688586407567595680114854000756390122*z1*z7+9283795669500331678592266147343831876945819789271729190885561085054683492695920645108158202159329590102021413247771351339719838365589856568827854621344878510738740875735205*z2*z7-9305345170747504235146505216011915981317381174484354658743951547771847409012299335728234870234391312000162398737135904843891591282655593912065246094825530254184260311806761*z3*z7+434595356272463060481519483650446891488512731684110669348777862685816307734298779082926381754791974631612198318410632631341360214310772202347128609393356799347365989782388183371914000*z7^2+32624985473813948280461416578042832857724451475300115186591315007576678755796948099082741946122399295558694529869046608084214033251615600702390818269628938356514146107101184*z1*z8+16273470786093874444603317494102005477052258241120314240527208697548126167806794781392208234900420621553541921978660877249012529688237330182381326966520268919231400194697216*z2*z8-16306225513984794741013784420730071241829869071874008125220713027472201046688168854371182413673370636098482172367574570474768939935473084385308032403627655244209754278520832*z3*z8+2446209508075732409636646233816392968931709403052563542318133167024652476976269923368225734112118781459684134139055016463502947678257458565787364049807474999279730178587596145410977792*z7*z8-1786011740887352383174491563513493504176620070678143243291061048114681086288339007402994010193685442981946559027385618721959829914450693155231916698730073473522229984901024306070387200000*z8^2-3445192349035170133479327601446845981851245667033461668396653580243565805763836143084239655213269103042401320798442452025326500349678195832970791869002223157784909917350*z1-1718136387238224189818187040208998090210151630796473382512285378411455633161492228454771761663524748427998529137321912327498038193144415988718505023545779151765182742163*z2+1722028351565094331429604742032529979234533981800267911209085058851992891295994988016392348588268525544108743217976214335721114389011678439467027675439902629134903446319*z3+31597748130392740040983806730779502607889782329838318207024303118827905592234913492736544584704025151015983529657048060788367215693130550002257987420484143938814218301688*z4+430083484799897788799516045531754668874690472870736385696923404961430252692240637966051553565851297715413932072390616619821890075573834784285597906632491679546086268966*z5-430151261456560166852357968414269612977520096945209773813650111045931585061890738141157833972283361468831292733182641671258426589949742237453527089093374731083556304500*z6-436037658553317229949514881364104119164659147661516833272005838159586595151896847962445855909976997069347558051993165601993090176110101283195534623798343669634895307301135449751015289*z7+176769783631657047120484346301414557844776122135214613967051796555305660268574036820135468140209909168216951855464610815152882380332578245524055237500741847454200767166162202880*z8-10450840602698342041033898876808441929269435034237475603496438332327414522412965622849688470331289714391537219615277968577740556685228178404213103860695674210298736569421012, 6621931758406030816422097531808589578309502975631572501956688778041482188991268339485159776838002121646540729693138691185114855567699540617562107597098847451360*z3*z5*z6+4354473886458275154590780202916320785941154572721544307355701375912270100044371435475500260862863021933393918509300532826076058312922582347744693364225742629145222126761576340225572864000000*z8^3-311805814410266884836412707051282538655393806712952952526151159049061724860432025417196170739693891122276417003325997977420348588530519877343072551026618791926062752*z1*z2+40750449541963884184060874693584232402067869732340795988680939738336217249256846889909059983508476453185283320836987537338565077493072418757090809932699986487893560*z2*z3+1861541922063251106759586290196096224143810668869066524030340968462725630796516269859842857667249546751531864718473230282217568418903072291671576161972822559581252312*z1*z4-311890999667863447716126815746419385237754749870018142152550624627576003012472953454235724740427548569924268170894271706438660644623032039585404185397117992213213652*z2*z4-932604047835659185017276796547062143044074374361633565776885155109427654083850525804465086845742203992508068344324788233719772795144010150158240935467744905261505308*z3*z4-6621931758406030816422097531808589578309502975631572501956688778041482188991268339485159776838002121646540729693138691185114855567699540617562107597098847451360*z3*z5-6621931758406030816422097531808589578309502975631572501956688778041482188991268339485159776838002121646540729693138691185114855567699540617562107597098847451360*z3*z6-24928275747492956792781803833121066536820678452498751215200125464157084141006657285729739589835780996213179600355295243738833576040785648439091511553073322210215754565168*z5*z6+24932939025684219162141977996870187464425129803926128724129989844139928358929937999323543997303029799798420655660295981363297523202711668468812651714631341296815975943439*z6^2+2095484098566264001468718023689513525208086159677659914387195464309831000454053814716913880216752879678855006391392812539269360427239471667263295048240039724001234491742101646*z1*z7+1022167745989867921871229856590678773616756224997380298530296284426780356992259671893850971698274933424113805914748393258862773602722455488406007313101877211886869316310386775*z2*z7-1044603914603343285589639131891969753371447644649772398676442583294936461904683476270254006447488707342107426733834330825626126639679892322396826878838639763183514676358337923*z3*z7+216134739030740436505965762881190524753127116725164842920528252354658461771319427064879194482333714899252181787160578274952187201034994758453675598080729968908243662278774914345810862000*z7^2+3111882434035115087951160719506788616095492555347963181264922744756194843204453602313241549510161906379986167339273148587654668308489967973546067393034001447708097209821294592*z1*z8+1521988084928417832085175943838456989948232070345127839361348146605329650874711149287425932296320704063563781972979794628228903696830934572122213948335998444133490383875790848*z2*z8-1551295374135282172619901058892804015240284306411792716228035299656051159145337495351668174313044929343317061108629947133729283155205648090912799885463345940925478612368316416*z3*z8+1062520531615929894016585895452491682622670986480286476480957730434971071485340955698372142568028684168005974414940093255079952569103914973552674102885782399849914335338620376527441268736*z7*z8-887475475482271555269394991916613770815362934075069630151488771415154433610379870515156218832336437969490621266121187789066563818203120087464969505366339840009652886542617987761146150400000*z8^2-232382017066282425903549641566563009423712593688744669343817771349361990066336477477226563729435817488510476438012973418320646015187768004730340101119277232566712390758050*z1-113379004300838468739345861374705113203271218642510630786415568517166299646052950140319197384676310561449040346912462615363819055993621698576507069926043556300379623846929*z2+115769680711579518432021015686444143710422726003566674837269307543638145671162011246789621382057963314451164034523288022087405992809881850838538038510232010192480398684197*z3-5514313607265162217504369584890800812717330398418901999038864538995484080162015696899981432757322754370937395060023521199965562368865695276704700195911669802376230771856*z4+24928275747492956792781803833121066536820678452498751215200125464157084141006657285729739589835780996213179600355295243738833576040785648439091511553073322210215754565168*z5-24937602303875481531502152160619308392029581155353506233059854224122772576853218712917348404770278603383661710965296718987761470364637688498533791876189360383416197321710*z6-216668730942241666321077686057250095286093488065731905770313381515399057193062496243532405233848836260808587578766262291302128018154663937833720879673723272828906739870970899220971215667*z7+27216685498606200345687602829711350710134020105152194262688795707248835459840117537505584438890516142136719717357312058952902729845271367917032918944107025920342954231775482551040*z8-688843461700880634195392785365894504809334217232307197635982380984027059692606074623940122402760301364274666851279713052082267805320034885985700844472384069242900613978072426, 9932897637609046224633146297712884367464254463447358752935033167062223283486902509227739665257003182469811094539708036777672283351549310926343161395648271177040*z2*z5*z6+9755638637994098071353840071831942867808977683219747355408720106317066945870899989036176882186677407670406807115119731707008717797973867961501280047351339293752845369338879033455637299200000*z8^3-1161123889178850871858378011066110646187130601445017822318524553567815960168845428679879085744018118614066093147931288555825644125753036066030356513176971811952462688*z1*z2+697924638127046903329148289646573751921563434923088213695584031902991014282380202460520877566991477925938218001819707271479051335568448215167734213232296010906622600*z2*z3+5194305496607252350910358460902959377755983757520097021836487755926886553321693537829392967643043049562518916838749846729489368138264983387130193860224458458891902728*z1*z4-868653962144707423418382583915466671485293143268584086834176174183235733486097066086569923185461093798388751806107330065732905580068604842501703051544322433912090108*z2*z4-2596065761987229227329827785151862004361748813988666751185007375736262420886946640834495937282245761923597196458980186956492569906095683552391633338353957688139815252*z3*z4-9932897637609046224633146297712884367464254463447358752935033167062223283486902509227739665257003182469811094539708036777672283351549310926343161395648271177040*z2*z5-9932897637609046224633146297712884367464254463447358752935033167062223283486902509227739665257003182469811094539708036777672283351549310926343161395648271177040*z2*z6-48042851290113388702825391010689785417263857146493322484756377275580220288284216453956477079165102247718623057040804230168391824381881417512232061751561267440193570515617*z5*z6+48058911756867876128876588047019613077414957615352889637877929720275304278722722248655367381516017087134834464747964618410822701770620979967214792908855647000171409967641*z6^2+6494504532780599566031069349707102181136374675410264852194505951571894685663743364455553231885138733618622596132188798086403055279775556354488342878716014496545395794399636194*z1*z7+3213437781943025115206229070452100413054071002071234309689444050873902554465850994433698553073830645679927646859285046320724847736273904366665234599991161495149471592473634785*z2*z7-3257778428292051870041579543339313748204511532026967103668413983747291996893241030925652979380605334233005782812317083612241529196301708063341499113789289122878498608139013077*z3*z7+449474638980183431675337149552193019975299959817723614170762079804472038493417399532480932949630281227245119342911136940612325293778400942038376188779397754544142575881513116556959778000*z7^2+9673282071161002751346616997527340331663396251888640720804314309203645495290172028814802286286380254540716654459710596630283682898276920895278824622031067159792561029454645248*z1*z8+4779896792315064299870159658609835695431437713696210863717872183189907601747309501263144642125877257169006828530773964204132495663877184277748780570956412242926686616676959232*z2*z8-4852326780110473994948582762551749031666394164726981480079918254939677304937913811139318856417114049500288323382471108234674710434928438622468783304336818976332756713866363904*z3*z8+2380254903343130590706827247005001085291118604573861671960347514859873656752990578279219300014265642004626978756445930027675217665870404313234870771430710146284030656649525372192902180864*z7*z8-1846299284330517540317034128805973630337984304584812555077042459352631277409707152744553921314620587481814143581736273839325775585164976784183100944111431640597323019346732230217995686400000*z8^2-782342693434686044296993004488607380820006582888433385028919001898752063499960576034010645905791666258979577070172044489243457080057231034094509382265040884506996227802990*z1-386134700447767500404241455713761752490542588341731827125209839018458150403158342632711018273117219006288377921986945780298259158520007572075103346520741011476438376898471*z2+392598589608471565113863010279526509585800886919308878414218835257893190404315233807168288609839901286205214996098687461831801464853087933865790119773731661314191701140643*z3-15508096519483276372307457083100592106343954803426740985745484554833144541657969500384184429727525879715217698355826947744448025203309753121238145709873786373768272553364*z4+48042851290113388702825391010689785417263857146493322484756377275580220288284216453956477079165102247718623057040804230168391824381881417512232061751561267440193570515617*z5-48074972223622363554927785083349440737566058084212456790999482164970388269161228043354257683866931926551045872455125006653253579159360542422197524066150026560149249419665*z6-450756426333923739193859221968248825658364196749531959783520220610828882639404960980150508225785684393997207855235951512976792815592954123607576757748449503042762466735501000382486579333*z7+78996770032568463660615475877366234955262717422674949391905872646456918965656952014970928050168900062520156714772261976437403084392227002179322087147252102496035420704509582859520*z8-2337796175677879658565571820612651779061711975020741656990306799453336559467552641962576893820785847892381364796865974194687836630721347804612365932019945572692440975592875559, -4612291591533495864563589460482473150304219293640978301094363272538705184851676416765794241740800*z3*z4*z6+1358917670227149505422599786070280370364285319233107629843046911601120048349876878075958987310882753505280*z1*z6*z7+680928211485515400617364578290430539334109991089021867236906972529449169683424578320444826179263320970240*z2*z6*z7-683860658000335605494249232547033922431127937835910643852064045259813787838463876865051623473463117706240*z3*z6*z7+3714896266681019657903515145611728456714436035622564116217002297391271152766164836060441542551511140036845600000*z6*z7^2+43678215286643728204448851743725386053751639698723364878433296885884549722013013425336838678655317127987200*z3*z5*z8+2025302521136794572445039112647939386389222873694447269598775572759571047136189957270762272509322681384960*z1*z6*z8+1012653266551715118850935079263501663275192131944561460355789844718596783024231888174485859350413671137280*z2*z6*z8-1021381878554954051785200367563935685894097395070521218230638004324141487118630471042995967912914654330880*z3*z6*z8-19675214787784052854330978888781328296424739302146429685923295189981951732355065442445553014744005363798752676623482880*z5*z7*z8+41458708790184311136163319489921012576361151375418857093318891239863085598588219071827236462566792267446065889280*z6*z7*z8+22808838665125689429553061280138519632381913777468160536126879086255179343792002800674831096598499289957290475520000*z6*z8^2+4612291591533495864563589460482473150304219293640978301094363272538705184851676416765794241740800*z3*z4+122660210322580815753515266836107959761898444134841417174037153607918501995304865173177140080032071856*z2*z5-1367996808424502568720398668575715587589987221369100005180131602407860541817051205478895590833040380*z3*z5+3969937771393512063776098580030964098429164807362778145604695489595473622907487175846989533056552311040*z4*z5-183960132588485947494255546991628777818760145322235244046632577602491890797872041476115201360266086400*z1*z6-91980050146442418127511715464461200457995976519087256896840630099611484990100731197758697110415590400*z2*z6+93368194484833045265805708883456230572783396801113339981344782605932598412502324643256039862982272000*z3*z6-3955222411514760255124540379471411980623733756518288331447822461108798961977156087261080276428861547520*z4*z6-1358917670227149505422599786070280370364285319233107629843046911601120048349876878075958987310882753505280*z1*z7-680928211485515400617364578290430539334109991089021867236906972529449169683424578320444826179263320970240*z2*z7+683860658000335605494249232547033922431127937835910643852064045259813787838463876865051623473463117706240*z3*z7+27631130321891715929004335044406166688329383468951467536250373405915529657844510591663159549735228222266545294304*z5*z7+5550977252322335414648597758701464967418603279902814203116663589724627686693175524310420513771341715413734231040*z6*z7-3714896266681019657903515145611728456714436035622564116217002297391271152766164836060441542551511140036845600000*z7^2-2025302521136794572445039112647939386389222873694447269598775572759571047136189957270762272509322681384960*z1*z8-1012653266551715118850935079263501663275192131944561460355789844718596783024231888174485859350413671137280*z2*z8-42656833408088774152663651376161450367857542303652843660202658881560408234894382954293842710742402473656320*z3*z8-244953081302623466365731071926456776167982140314301511328679609783560121387206059661373400967622639114932961280*z5*z8-14963375757627184660210918756316635508364821273243019947497255478957905663677085358713793378333049855935447040*z6*z8+19675173329075262670019842725461838375412162940995054267066201871090711869269466854226481187507542797006485230557593600*z7*z8-22808838665125689429553061280138519632381913777468160536126879086255179343792002800674831096598499289957290475520000*z8^2+183960132588485947494255546991628777818760145322235244046632577602491890797872041476115201360266086400*z1-30680160176138397626003551371646759303902467615754160277196523508307017005204133975418442969616481456*z2-92000197676408542697085310214880514985193409579744239976164651003524737870685273437777144272149231620*z3-14715359878751808651558200559552117805431050844489814156873028486674660930331088585909256627690763520*z4-970088077361215725285382011143527091471531310091941239266318934989797019208397414277425451201660772827767*z5+1529758380462225837395690697821218103679216890391599665200137155188849232939570036455745189556987620289280*z6-33182107574214051343652932803107631655747986748854281739367036995640157344537686115973580063506569937680279525344*z7+259916457060250651025941990682773411676346961587544531276176865262518027050883145020087194345955688970868408320*z8-559670303101010112110308686677691012207685580299658425933818220199052213731172622178319738355326847461513, -358733790452605233910501402481970133912550389505409423418450476753010403266241499081783996579840*z2*z4*z6+231773852614792022780566618043554418536726337304855403230053499698986017837348650602699943502584808929280*z1*z6*z7+115361644960189455214156276219899235794988353225915787401970433024889782842447677220390302142636879764480*z2*z6*z7-115977885918793747754935962718641583867412084720731850825174612717099448242078145891296590476075979914240*z3*z6*z7+1065168769792923670615410973567143397059074995431679720918653246289303983951071001209993092884310638013841382240000*z6*z7^2+2929073515885428017209981890919297217812232214435853655558027727090032425173984045276921796658426019840*z3*z5*z8+344872551172070899111074968414214792304045123889130524104644014313352202917270983303928016542496273203200*z1*z6*z8+171484996627508716851319989210354231979864205307010200035220423181973211717698854287558550836011658117120*z2*z6*z8-172571950723660350895719873118586644948968392589811367592346601444051934827932714397937580442342861045760*z3*z6*z8+2295082493484784050976620894031587224993225855828213410020685432175942020196403548371841335653950096264670590980915200*z5*z7*z8+14567144549489697052495926464348755079336918862199206305678315972371283854223372163165168774773932924354694676480*z6*z7*z8-4344058996532777382572595393511143594113448445554413536116911498254133024296665542358236174946758879038640766320640000*z6*z8^2+358733790452605233910501402481970133912550389505409423418450476753010403266241499081783996579840*z2*z4+20754108879094805264603122034631961472421680415795773328971503928150781993860435290365653738497427088*z2*z5-8901375369136083137871879622031829512406506208695213589766364590170954915682687983576801640348820*z3*z5+848778215934708074917179892622851179638943157762739982092941517075489406736132828900763469296530932480*z4*z5-31306509023161658040022170106160463939202576957587440055649097700421755799924804646901376328167495680*z1*z6-15532925518172917062549510432318553691975680451419035762977813624303761532070299659495948500349332480*z2*z6+15665586310318893065216898124621722443431645042924402570032264694793324967919913149978751254549171200*z3*z6-856854265765608618079354652267739508175748855176396932808391979123556376610721656729732572341852359680*z4*z6-231773852614792022780566618043554418536726337304855403230053499698986017837348650602699943502584808929280*z1*z7-115361644960189455214156276219899235794988353225915787401970433024889782842447677220390302142636879764480*z2*z7+115977885918793747754935962718641583867412084720731850825174612717099448242078145891296590476075979914240*z3*z7+4704340638118670690283341175931813897039535238050173031405898836838412152463111330399069244160307930132911982752*z5*z7-1060566319046804308628681445807783734564426803826113314519030667795996620524986491567173060611421127697296940661760*z6*z7-1065168769792923670615410973567143397059074995431679720918653246289303983951071001209993092884310638013841382240000*z7^2-344872551172070899111074968414214792304045123889130524104644014313352202917270983303928016542496273203200*z1*z8-171484996627508716851319989210354231979864205307010200035220423181973211717698854287558550836011658117120*z2*z8+169642877207774922878509891227667347731156160375375513936788573716961902402758730352660658645684435025920*z3*z8+56518091534684910139038186147154200090959513207314686156415785212702804939259651491025819726663817054882283520*z5*z8-3765511759238196808362024723769264760919026178382936942991653386798914843046220038507726338455114709881651200*z6*z8-2295097060629333540673673389958051573748305192747075609226991110491914391480257771744004500822724870197594945675591680*z7*z8+4344058996532777382572595393511143594113448445554413536116911498254133024296665542358236174946758879038640766320640000*z8^2+31306509023161658040022170106160463939202576957587440055649097700421755799924804646901376328167495680*z1-5221183360921888202053611602313407780445999964376737565993690303847020461790135630869705238148094608*z2-15656684934949756982079026244999690613919238536715707356442498330203154013004230461995174452908822380*z3+8076049830900543162174759644888328536805697413656950715450462048066969874588827828969103045321427200*z4-257344360840286668876288618816672557644506343888791572935037520128828610317995427124655120507814138047181*z5+352589689333687828059481331145595578496890008927653819653187761694265049364656965361752837264138106128640*z6+1055861978408685637938398104631851920667387268588063141487624768959158208372523380236773991367260819767164028679008*z7-52752579775446713330676161423384935330040487028931749213424131825903890096213431452518093388208702345000632320*z8-95245328493401159183192712328923020852383665038862246718150241565436439046661538237097716756323968081459, 64572082281468942103890252446754624104259070110973696215321085815541872587923469834721119384371200*z1*z4*z6+11449958358999805850160949957288001733302877529361730508835991427661624705415065671028456814676150031800320*z1*z6*z7+5667440453847063981753416430696124292264346836477159285340389755996024810802589371788011241702485433666560*z2*z6*z7-5702330576319427804189838476396762144244260014194357293817128862281417439492903915465192435651415794396160*z3*z6*z7+95839241210172611852117559392960235106232103981449138637532735964079529328159398543120868453954343589724969906400000*z6*z7^2-305886208553104925541761198783199360504070416354689786869910552481957928319028120844158923126744060657664000*z3*z5*z8+17044843816526917319846220712225685554115374568622988732429782822813825209805805818214602748593937333616640*z1*z6*z8+8436825815640444540441333851930945529492854045692852422000587713415003832947467873812472243561064937553920*z2*z6*z8-8473485282048963858677468410294092347153378239907781987567495640387295284962642942878522391161365864120320*z3*z6*z8+68831501604920039205604838237035840754300403923809683465448506705053572448328813844679500682339085341298334233120276480*z5*z7*z8+1021667279771053494448641156613144303829007710492651528193117279825533420085362958590070871642948287508076861521920*z6*z7*z8-391124626483620413052170743426216137722053408811707124714485115346989050196685906140435650114487789605154875574845440000*z6*z8^2-64572082281468942103890252446754624104259070110973696215321085815541872587923469834721119384371200*z1*z4+1025915019215730296722461242849268809591128580653041412006353927217656570532627119479634262305214069968*z2*z5+8780596564705601843807592233412852238100741036967405618580185627018987102906422666056500360604882460*z3*z5+49505710264607645337064516347208420068696762139948579753221240002775668038915028791893967307859550498560*z4*z5-1554860813642298182781297119371015977757469503686785701451186253892514986733224938813065800613461555200*z1*z6-766600910204740783744207654573736611349990356797883713658037380739498130631027073177740430762712652800*z2*z6+768820368264607813674879100102141884607842872650736304386903124477454366199690796933729969698587622400*z3*z6-49549467409858512522390936359633091020094090509084298775880406819322323593132774931431891502587947514880*z4*z6-11449958358999805850160949957288001733302877529361730508835991427661624705415065671028456814676150031800320*z1*z7-5667440453847063981753416430696124292264346836477159285340389755996024810802589371788011241702485433666560*z2*z7+5702330576319427804189838476396762144244260014194357293817128862281417439492903915465192435651415794396160*z3*z7+233724957286473578023888675735809673970547579805998587853670693188458842932421755747337308671947387838493496656672*z5*z7-95489741725454078200971501930970085927118480432275092196374436286832451831178922746964759708771473066153047102499840*z6*z7-95839241210172611852117559392960235106232103981449138637532735964079529328159398543120868453954343589724969906400000*z7^2-17044843816526917319846220712225685554115374568622988732429782822813825209805805818214602748593937333616640*z1*z8-8436825815640444540441333851930945529492854045692852422000587713415003832947467873812472243561064937553920*z2*z8+314359693835153889400438667193493452851223794594597568857478048122345223603990763787037445517905426521784320*z3*z8+1216441053784211236018427216885125205254533253236308241578068504649978598344249262707798530796824791398427770880*z5*z8-234547562329242436683353880820397594172193612912359659026582638800904370008584511388813350505068717056968949760*z6*z8-68832523272199810259099286878192453898604232931520176116976699822333397981748899207638090753210728289585842309981798400*z7*z8+391124626483620413052170743426216137722053408811707124714485115346989050196685906140435650114487789605154875574845440000*z8^2+1554860813642298182781297119371015977757469503686785701451186253892514986733224938813065800613461555200*z1-259314109010989512978253588275532198241138223855157698348316546478158439901600046301893831542501417168*z2-777600964829313415518686692335554736845943613687703710005483310104473353302597219599786470059192504860*z3+43757145250867185326420012424670951397328369135719022659166816546655554217746139537924194728397016320*z4-16337893679833496725977482484475907522158932474294106037990879125617439420097781338152913473830227854166721*z5+21068329127837169625113359917941348726920506925718972650250393707353368492204563993175214844035048925195520*z6+95256016768167604622947613255234276253147932852469093608520765593643992988246500991217422400099525678314553605843168*z7-981893491454968799335073336064727611082339640323948582551485865849074228335664751318985180291756074341458821120*z8-4730435448003672899135877433465441204761574451424866612259514581735929072106782655022301370204821071028799, -5005587773757282333634903290446094891803028690773154745373727582600145161854532545327218556928*z2*z3*z6+152433124065965068937185576706184970881324084350679250720553465640789503277638167629117850437322966505472*z1*z6*z7+75586187493659307036862557138982257250906404184120890382707895281060250678960079661580047349296567708672*z2*z6*z7-76051663149266558934489450265677743689919212403837616276262688969226882146126053009214239226620393638912*z3*z6*z7+1278202430403125056462223960230398670822149963620345987887824382923405519951559894207294314203533842872343346656000*z6*z7^2-244868860916241801951841665702773608781723549013120034614494930484226585742990634907307765606208503808*z3*z5*z8+226510292575571985678105086076451165784901797272567374846391080277898581463687736500077614488700161359872*z1*z6*z8+112521252519046835443988395187562735612622369256406629462472971458487705441754465411905245559496119943168*z2*z6*z8-113010398053721943535028884171314831447916352689075280908955917425539433242959866668852428729513900769280*z3*z6*z8-178817019845467410986367280943008930456799208975681303522004738995054300777115565223506244753262232445622031155200*z5*z7*z8+13625918128804067711264127860807173651603036945526789741427090726801534989833214665512828090895450828417179254784*z6*z7*z8-5216406576256378802377483368564494799890228575631339164419944819259313855727534857271313526816265803217293714391040000*z6*z8^2+5005587773757282333634903290446094891803028690773154745373727582600145161854532545327218556928*z2*z3+13671998915757359779761311976212997919347777721591821478681184468053215606170007814640700816920691792*z2*z5-36390439229317789139340395003844380395564822947577175712536544425623991905715067214784863742781508*z3*z5+660910804347243992203781303291193840194444896854891624593082630503776301394058785135299896516354889472*z4*z5-20551869633050098318168674736214180448066820002304172313965542354787683176978918983661763829431941120*z1*z6-10224093342778090935645267029571700641708293661579255835494943582762874742029191311651400793912638464*z2*z6+10253694124154237480544825256320174608898335777442620066366672976709660018551807893310749500593527808*z3*z6-660838441890112985946868832716961400044014615529898090432597049235419103673483479352514279700655676416*z4*z6-152433124065965068937185576706184970881324084350679250720553465640789503277638167629117850437322966505472*z1*z7-75586187493659307036862557138982257250906404184120890382707895281060250678960079661580047349296567708672*z2*z7+76051663149266558934489450265677743689919212403837616276262688969226882146126053009214239226620393638912*z3*z7+3107662630648943435456485986826839122119428532961299850254402865337706967950861702064043051393949572927199057440*z5*z7-1273541175814036403309298587348141624969051384790443741447734507838818961683568739902114536751767945052025988697088*z6*z7-1278202430403125056462223960230398670822149963620345987887824382923405519951559894207294314203533842872343346656000*z7^2-226510292575571985678105086076451165784901797272567374846391080277898581463687736500077614488700161359872*z1*z8-112521252519046835443988395187562735612622369256406629462472971458487705441754465411905245559496119943168*z2*z8+113255266914638185336980725837017605056698076238088400943570412356023659828702857303759736495120109273088*z3*z8+3810607565544557769999063198452457637888395171153223627029267871282629735462426037605064439420374406847774720*z5*z8-3128147510104756019287636552677689171354130613767787913352210337929488942302212584301234501601129051801583616*z6*z8+165191101716663343275103153082201756805196172030154513780577648268252765787282350557993416662366781617204851900416*z7*z8+5216406576256378802377483368564494799890228575631339164419944819259313855727534857271313526816265803217293714391040000*z8^2+20551869633050098318168674736214180448066820002304172313965542354787683176978918983661763829431941120*z1-3447905572979268844116044946641297277639484060012565643186240885290340864140816502989300023008053328*z2-10217303684924919691405484861316330228502770954495042890654136432284036026646092826095964636850746300*z3-72362457131006256912470574232440150430281324993534160485581268357197720575305782785616815699213056*z4-218090183271963995235473524099163234436017696854885779999990323668308606830895598358864841473104728560409*z5+280987110890015552008397663556586222100371157004404470386269355215832963704645459711423229609215825405184*z6+1270433513183387459873842101361314785846931956257482441597480104973481254715617878200050493700373995479098789639648*z7-682460055439801750711426645774768466534264557385435713677057533353140793160213453303829937819245355046191104*z8-62896927618051556772924139457422987664353460149518690386279031547524356873749861352558388136111096844775, -750838166063592350045235493566914233770454303615973211806059137390021774278179881799082783539200*z1*z2*z6+32379986492056271617484766706788913061530487493572203374772798310419179024296041929634332283045451207792640*z1*z6*z7+16105725480762737296429128177237731863877372123454581421687196177769621149082080126567256673315201709624320*z2*z6*z7-16185781087190721060586804939355734951799960967657240950784348860245636392988800416280723953723027261598720*z3*z6*z7+191756375865370125271285097969401071591523916532544579795422654687982206097570591742744660679127135625642895564000000*z6*z7^2-6209743861785763200467071222387699433298642549555847775129807705112674720478128773544425833701336678400*z3*z5*z8+48157527817150886223219680282117058811171100276190245778534987435352686879329718558024554517342456439111680*z1*z6*z8+23968693884474934910296252803131247788616040452887809004555662187847212320058032897362677771283575317463040*z2*z6*z8-24072572256433594973031548215683927255398959173008618868232125880965614251321699826501331386336440040816640*z3*z6*z8-27109681889595424951632838485292910568782295136181686383238514114870868496394805882103076085784144711665273019760640*z5*z7*z8+2334177148111316376060784646579078687212143028184072652209811581013396978675743447268979089931058586205373498327040*z6*z7*z8-782301281398430298604467201654696479933519641239486383623533892774274848430222038322729765511599651756262601371156480000*z6*z8^2+750838166063592350045235493566914233770454303615973211806059137390021774278179881799082783539200*z1*z2+2906606608771123410819276012495968372678834413471817303566485418692642751345835542506756652047966760656*z2*z5-3527402708903328120668492187098794690732193562642758133545572115176003807031912922895219005359457380*z3*z5+126835345088589292291425830066580060328230091070823136245722804394906262650961230065870322031088474853120*z4*z5-4370855553718833451540272467730980726495673958210361921037575827652631775263236655193491388147477248000*z1*z6-2177651442732206810926916319157471129470154149874030049656184389186637153140194449391687492011281996800*z2*z6+2184866132670863515293246304463473330078008212040088237434935971645285616722278227799707404158491212800*z3*z6-126819938242148262274694514268356107832856215017450376415670497343657244810419733717546354948783546792960*z4*z6-32379986492056271617484766706788913061530487493572203374772798310419179024296041929634332283045451207792640*z1*z7-16105725480762737296429128177237731863877372123454581421687196177769621149082080126567256673315201709624320*z2*z7+16185781087190721060586804939355734951799960967657240950784348860245636392988800416280723953723027261598720*z3*z7+656877706439069704752666283721828805945759761435294539786716685254629690187903247641405200667578299008237808129824*z5*z7-190992309025269194022065179230261183756780068322847035953881982380513598279755600020762013669920343574820441960852480*z6*z7-191756375865370125271285097969401071591523916532544579795422654687982206097570591742744660679127135625642895564000000*z7^2-48157527817150886223219680282117058811171100276190245778534987435352686879329718558024554517342456439111680*z1*z8-23968693884474934910296252803131247788616040452887809004555662187847212320058032897362677771283575317463040*z2*z8+24078782000295380736232015286906314954832257815558174716007255688670726926042177955274875812170141377495040*z3*z8+719508980121519607466475902713662166219020728334058882517337497066745224971848311381829541743568083132550594560*z5*z8-573994199764603521845159819434315528811212827141368395813655739345297554226648179594193392914729863915919441920*z6*z8+24775504741484108575572053838713831881570152107997613731028702533857471517719062434834096995853086125459899521433600*z7*z8+782301281398430298604467201654696479933519641239486383623533892774274848430222038322729765511599651756262601371156480000*z8^2+4370855553718833451540272467730980726495673958210361921037575827652631775263236655193491388147477248000*z1-728955166038916599892359693338497243208680263597787253910301029506005598205641093115069160036684763856*z2-2181338729961960187172577812276374535387276018477445479301390399530109612915246314876812185153131755420*z3-15406846441030016731315798223952495373876053372759830052307051249017840541496348323967082304928060160*z4-39561628184147613090927780261497013546284630221882216305162620742262413286706529969887187342747266498025057*z5+52859298383087252151216151904912418435912953830189910241208673938745876160697852838593013900112854331690240*z6+190335431318830124317312512946539354950834308561411741414095265695258968589567696773120608469252765275812204152722656*z7-145514780356916085621316083279346637407807901192690486703681757721447670745200131787636148828838219216631152640*z8-13297670198939639060288371643415404889628323608307693936046053196483462873991322868705826557365587833665183, 2*z3*z4*z5-18936133504*z3*z5*z8+8531626151614399561728*z5*z7*z8-2*z3*z4-6099*z4*z5+18936133504*z3*z8+115377986429760*z5*z8-8531626151614399561728*z7*z8+6099*z4-115377986429760*z8, 197413632*z2*z4*z5-1537312071659520*z3*z5*z8-1263125273384819448597171290112*z5*z7*z8-197413632*z2*z4+4504979051821*z4*z5+1537312071659520*z3*z8-28457455989492776053952*z5*z8+1263125273384819448597171290112*z7*z8-4504979051821*z4+28457455989492776053952*z8, 18249*z2*z3*z5-18249*z2*z3-74151786*z2*z5+221968654*z3*z5-66664284820550857440*z5*z7+74151786*z2-221968654*z3-1352307873378*z5+66664284820550857440*z7+1352307873378, 189828710407639550070766795911846234578205751968105078389425078303855822751083025731907913602689394153867500917869975813973292526274053497703447084450166960272320*z2*z3*z4+2387366870873212454361134167516643883954186477593214148948365168980378509964067857904661877008024132846541690990024740407196696465819102151291043580844943840052585457877387045251019571200000*z8^3-274490254077626289220411467341978559801145484705098707073077992347947818675507349258534063677422964917604105485823045159522270587419996671255194123635590747452170208*z1*z2+73336004740155489456977603068623091634137305749523251108110853311028676130505100202732987130602601844328853184204056230946713954707658599154568627869390799632052520*z2*z3-3609166756509634903032053223191652910309475162140277249972484591349317928359496926052430326212687801356526552715433996449843923870775609311887196138175521629420759992*z1*z4-170331777911873758230718742470696418157154626993184245642718338641442373233541863045643695740144954677962242374168095613437298474345162132301335967590151938474646428*z2*z4+4113370562346936184982573621075086244307618055726832675312171160258204471665440318953944012942940907047470210762745084264474643261950287129837469312485838407518910028*z3*z4-13736274205656251058929087149750020527867609850050406866495403883453837792431894478482518580836188520964653525418647782079197155211756235750888731204970660716248254454602*z5*z6+13738785619900447687230374380819886214602884696284238418582763562449496521401376031558776276176508198922629732621592766898842818504369814055145200526818813136638336324541*z6^2+1132899193989717905884950587935799006428553517704904475912600777122379866042532018073081030073898488753544399630395576543504362064234447128493339354497949436345918866455773194*z1*z7+552743609317534137078441203765016434618055466239600419555347686175408776037080746719703914804039774189098010609031095197103723059436822732352950476998841404635612256287151925*z2*z7-563621380335185566912343819339321678023911246092916754269563102481968423119103645003062232313152462469374277341095912235716631043170812245631632185717440312824236732075631097*z3*z7+118787818894691182703751817982739031121651709399740074293630273573690548573226430698762837470223842836323983460182860090251707540094094992369478347327462375021753869904633875236191018000*z7^2+1679973802673214841517461931413867190803815424362863290938712686426637165676585539217041891876802586816327956086790847743428693140171503929106168878365600745045562193752014848*z1*z8+823064716408428744878580766373395554679943382007340551459700878683187616800240544008018760865287708676755757829538083868870570738462389485706717048672803462296125093905457152*z2*z8-834698624835631886546048819520604182456006744186195708621235465330916559277920996304466887212175325259951061124693130668927063077211469793821713922773283942651812399303368704*z3*z8+582534917604907123100491476746854014916950046623379960885885110374609169573411274790186610312632403406991338264952896916779980434247112622729469315322650787009229335579702858109582290944*z7*z8-487751332392812618107899354444418265567643301530616674120304330402992910029266275028479848536741137205486830417196542275474563722586567084138979029637965834749934025401114123333590080000000*z8^2-124290821209827081886854813229044166437910484278242602118187475880542316028665412858677530053165692084361887452959098779286595001319656021028644841345082110273925825668230*z1-61059558895673026684893571983759068982058256314309693325263457470274727925312728260058825147619653875457197954451991859036484187184537566074681731625110968317242324835971*z2+61367668654087812378729413775023830979111188965455828311392311587091653129415912933118737685820463114969140803667707784595703950314649979631295642069407498959384603791583*z3-3006043131745274974198827335712771799767168571939312579298410517140377910714966358835682518641781488458608152498100546948998279519037418743223295720663897776141371177944*z4+13736274205656251058929087149750020527867609850050406866495403883453837792431894478482518580836188520964653525418647782079197155211756235750888731204970660716248254454602*z5-13741297034144644315531661611889751901338159542518069970670123241445155250370857584635033971516827876880605939824537751718488481796983392359401669848666965557028418194480*z6-119079868160491025522138219261485680053012006636991980237545731503736505353003351259965683234529066186710901418370820660260797106208953647199995421356206521935650398679815697462853535433*z7+14770523721532557996557377911286692873211978142819994164673926198813336610596210612135838627321466423318752222734642473549744428764214788065058367405167293302485636930917344641280*z8-370964103986985492521409034130121234471540410686395199556981674603721468435220122245415217211258771867423678232825407425014648972620930887431307561316885517380689286010070904, 3416916787337511901273802326413232222407703535425891411009651409469404809519494463174342444848409094769615016521659564651519265472932962958662047520103005284901760*z1*z2*z4+32543081123586108443991234199078961348809506940568821850410103106652779305761999332645745603484947158461749031100568191983885976255456817665957681497306666939400883658899864445419477401600000*z8^3-3743679099138902625428896562760537766089269919678752529860446354194186142105167073988054729045890079192204578882404623856116467107480760035381196735186994896634510368*z1*z2+1429711562820568206932150885359603172748711054935973319447609457148158533074370672284147923929622605813138227911246688778404344863908583158595704756595831933159863000*z2*z3+14998418438898408025566320657542898482286150904904896471859211646009354833793916826655300106239758187395467693099719460156380039220681980694820118274877825558323879288*z1*z4-2511181499147161295504233393589850754755136181994618277533916340224980032949642628894274312843646389077534082136868116338018373988705483155779842379568598009191232388*z2*z4+13284524516400201164191923883162721361525690610265667935035714078008565897080298514504604896560022741409959069959084326129535466350710099942044158585109299342352947028*z3*z4-177551499823906525391263831986560066080543784092382087898340185713290309040605190318933591188771110914824314048151378368195221074149390738561130651436984557438266062754132*z5*z6+177592083167936245134584971749667428927971636206216467586577507895398068674473214648315216991223854685633579866821913590103696885554554153308914716454668472813204615222851*z6^2+17560341213804989073997544028936451893515932073233337091326450802930489449751865171295651924146136404110200067539322537213960244197705720086517688481942737624254021291391125174*z1*z7+8609879587951892617973103362516782202459427463483429579868793714882775333532543637025866708281409482087119456576427399598953186097862266497527473178427281558078047997006779435*z2*z7-8766655466400824127057736053120928858099115080105812529368876114823178996656149631624736794476071296611706202535978210385080282518290145041321513952987931019924187770590509927*z3*z7+1578481318995894711087233265601636909580912347915483954483219079596286227738877448967675298413403873860289745011896195285977445464519709821823599721868705199230297670024932524385153238000*z7^2+26108174080833981441314789881482301692977118118672809554462898818815921449443343108112892763556373768297221391601056930914911188021972619909569385509450298198693441440588566528*z1*z8+12814815243729383641406689978013816195988185461370888738199971698664152786434464927839587849457642809372256928000030790741620694243250981346986793675829944419022576814794401792*z2*z8-13024280112383818206243600083453916260319617063971935589597384975834978563044478728100934628769048326403134828029881044437238654059215106908286557229407894467560972161046841344*z3*z8+7940530949584756889865639289551004363821718237347858902310224787132223303720518088676333428148087711108104753607190885267362319701074012397719747044455321995036155438745655057467298893824*z7*z8-6482179377947724573295030043109801157425672348649585061848670809670629743168108985446929040096395776195321092472018807104700670663331762643496130605442108293174491042611965414034000422400000*z8^2-2013987377270272284701023239732986271951536537584453747777592682283456515262994621183968565023309821642458072654378842835496565570814523684108221391800961996120148853646010*z1-986772053676743580889843270330826830991077355865553944144308603903352498139736297651906361319544978373467278633050003222933338910350856292260000655352888091390146629910301*z2+1001611571803821041843263422989948867712096095947986981832470773184100913580375963189733056429946563093424965999422541264878831695911313743965352757591082810756786989606593*z3-44560886670918492380976395667278848416401962703720174102577126803342212065442203987519237824469127206200137518907922986698425442956211977652888114445533698322329481035104*z4+177551499823906525391263831986560066080543784092382087898340185713290309040605190318933591188771110914824314048151378368195221074149390738561130651436984557438266062754132*z5-177632666511965964877906111512774791775399488320050847274814830077505828308341238977696842793676598456442845685492448812012172696959717568056698781472352388188143167691570*z6-1582562635588066959547886338741630111928135903491050883898628257802885227646739716418750345307364254573499738010706350638992844820670186305595593443920097280610782316961162957916762920663*z7+222547193281748896470002173448890062577318715495956090216184160096767308351612385293498200031869056632058721775140373013728822971417860259417039585544458454416505142195001590521600*z8-5995993646399256073596734108673973048768484813130338867556390137011102970858279881847882282237012250682087238094019168666473670590455253548312023017702837501423570231516670854, 111716993196230518420093219091222261354919399967708235654545947277768664962554955801785591257967964157361315533034839163781513728549502416835087710968987383412976474664010098132428949753174250666535164172889953897097356902400000*z8^4+562775079025057483114748926705344090649618388185663391783403318027561331102695232762748799024660513074006141733507803004883823652348020332194228886681676190521009534766895585439104901443179137698152257403263309247283200000*z8^3+6091681557858190858791294329858813320738451430446876464255459835100406938963541497637694920784673674120429791179462463576504524731463601696634000564315866379425384283304076040248950695618409675104*z1*z2-1144471664497633890762163109073834311931545779102574548628515697183744908008549733529890411285543846374535849003964830252380112232860471234734914137232704893223809782410846540495907156154069556680*z2*z3+163765085406870321400992296455579757330641328333635190236381674194190022190854075224311875190208468644424814584938117506470325243532612425916472173290522023596172472293403481944296432932210996997976*z1*z4-27290528134006096626317450012939716694721178202239740260866950384189646170231645555606222043178647445533312506331408090952765111478349091625182319048506786041815635826888925936499332260318462147476*z2*z4-81873592860972177369198516463751834312004963911605295370702342319765802906501867145837580412419057943883888095746566342926882035010566292909017528713766524197172115606131881333130440867305011003484*z3*z4-2135036503571048755388470568752447389226752947901134600780155800981531216436374827718874350672966998372381475653847143023361786171330234518136264792116174061611096559559002791414494361016015920111531614*z5*z6+2135417866142766528076201067909366588735593031854512905908253102520346639550172821314316316043909018470488870719092196943073032827336158323741756470065093436295407156829983796800070819078514125450766947*z6^2+168883363077167584077920541233167744780262690584281718455380553727476657193523336359130033245860204191487052918254824713989271038661279593907315209094604303983665740345864536979538227148777561045114650297838*z1*z7+84428508484334181040354622531525374609706299744056534032088551784046990869481054976717611077720519404917046871340430286549548786018539217937214282402826976727361344588474318006931705885297687419322480311815*z2*z7-84613005351340388251773017697892661015231207139794298634557870718293024597743239578305912122326512304485941127999654949733533736101901369151611483972400255236789387054775035425215004232277292529921669863539*z3*z7+6696287439438600155695059765873757230886095534857737429442275916256200292190255666483124828222030659123363007649816951902387277416250966685430285317798793895476475973464721678361717481356811358763712108709853918456526000*z7^2+251485519893385461894779829592582035385401609815891542763495971111475242174207828828924133731839511421212296510971517630396829153853043030380689198079135229885274665345034186992230106539357956595482492297216*z1*z8+125595178449894904119418923001001898156727249301929062214644124248488713050132179665279777207225762712070623320379474954248618868541711013960267051374571644791493595423418282879290179413776750515848532496384*z2*z8-125997621488097246270640018237821583239539209907098773732373350695581533599997898833465963887756207850964885699277809360028462572035997776233639004673150930900947305442006382868639892590911062234988972576768*z3*z8+137339576802422704051202598264862369832654656573495285498289559884328506046654699310080295279649068459889828428338942143454433352607605816545890354499318170631531078708115568905518840113184246075648218821090745303502848*z7*z8-54702887312663092733947713313493539141153860401976115184197207051187144167817857934049062376971691352749633738021766537698023092152930290972208220406379895107863499970841008660001056829184241332658584973073465886404986368000*z8^2-18579294151216119634765648633454113578775060368380567149086892986530766266881650191455255331966674331554517342260575656071174262126997324852189104827950824683497830755561450737083988736616301521013696610*z1-9271218453915541088357540104526272446362057686545035842571830741523344258511862581186912685908054488779622922797597738039962664499055061622374762155928576957606952708740945739891749425297346962217035057*z2+9312789384777945904561680468289275415936693372957328566382718471490886130525222882879495058573026294525496710101535100602579653708465148560641485306722124620662599690127443113997446070503490534423813861*z3-482776281694158045189738041104046088553880020695656380029846962047710383852696766607320897212024734483887433785948082037299048011204580324277998493410539979112519680886609959489978132243907351590591288*z4+2135036503571048755388470568752447389226752947901134600780155800981531216436374827718874350672966998372381475653847143023361786171330234518136264792116174061611096559559002791414494361016015920111531614*z5-2135799228714484300763931567066285788244433115807891211036350404059162062663970814909758281414851038568596265784337250862784279483342082129347248148014012810979717754100964802185647277141012330790002280*z6-13355197090023941642096491067407532306153658966937013637915046356312250758338712030167367059103254908778327791608576308398523333398846414351114928978113720857914920053631298260847145652018695579065736826732042386003388131*z7+2335258094435904245506068917056166331086472022024460948115613160089902784630165716975557666040330170175018828258174923359914906343432592232190648986774885802572978722104517727180438669100861443406010080771413760*z8-56317616648683424795085064269388862647827269498450971284541322077335401461620221879323573238489796696617007704900159245789597461540639164489550983849509564211598852693233497517694824556997852708821580465608, -99837379719288449612216746146198506555242627004066244793050305000671529672901200539292309210531086416016303446788442528153600000*z6*z8^3+258749954288687326262086275028307213895324903795606368647491141040158108996888503545032093168735882168057259776000*z1*z6*z7+129234966713433553033788970555213615640029122859588322624805060348327200439666465697866832607122516733420380032000*z2*z6*z7-129444850153084819114238086599852766586741922355542681321090877199623030557948690233647462215577640458277522304000*z3*z6*z7-3283654765258692437327775970800814455138150229397366752894560672921631935910331096383365025166395740850833668075132916000000*z6*z7^2+104047297425960522422816276738314434869838438694935603996539902836413018081335540734280698201367938485342699520*z3*z5*z8+385011872811391454262998892520530556727640347363421256744102896580517542141594398776486230454618906706119098368000*z1*z6*z8+192297843950906012103546726188734326794267650125077608915077359733753966708279743135911616061518806531792896000000*z2*z6*z8-192610017906111792018391697671214632446282875686417242030728164404426236050839706711186156947148570072696946688000*z3*z6*z8-81055601265000625287058016798182641244581121583199778113850281177006660510996836525412044650815567523340800434133744680960*z5*z7*z8-24340144409800498723878477357056442838064698825311954795113128023240355954303553815607091088970065125194639614130814984192000*z6*z7*z8+13527766989405819274203359966587681837000201620823569536205981765780595958254141932179251866078163967634253671852945529896960000*z6*z8^2+99837379719288449612216746146198506555242627004066244793050305000671529672901200539292309210531086416016303446788442528153600000*z8^3+23298872433084580423535075221052760445023158830739513355008476441798053998398645978179674501710152914586702288*z2*z5-5623191240078242713765323829301001861418136488039930887479992086616800538380336395600213558409996026274340*z3*z5+1127720967674893010503325349446817355357073069127430947447411391246166022941281391676924579474983196469500583680*z4*z5-34956734731384333535821659297350404261674145929396812495708569396840749628540936777067518079322684117302016000*z1*z6-17468918702280237314768594041307932301959770892943812127674083953870096486203397627250825527717193374828928000*z2*z6+17487821169581499452583364589720763337708547812816457828249485018421649461911690670942744719547995317065088000*z3*z6-1127597468863397341521839341046265261650197584179583855303595787525163446350224031513097224700755609476664704000*z4*z6-258749954288687326262086275028307213895324903795606368647491141040158108996888503545032093168735882168057259776000*z1*z7-129234966713433553033788970555213615640029122859588322624805060348327200439666465697866832607122516733420380032000*z2*z7+129444850153084819114238086599852766586741922355542681321090877199623030557948690233647462215577640458277522304000*z3*z7+5256248108585071710402955164456067556233316493362302351074434628118789972259656026184514232797008699351313403526359450912*z5*z7+3302668463073461590417874541623726128045093914069221921384082075758940748395276069292530714520235987580094008730644069504000*z6*z7+3283654765258692437327775970800814455138150229397366752894560672921631935910331096383365025166395740850833668075132916000000*z7^2-385011872811391454262998892520530556727640347363421256744102896580517542141594398776486230454618906706119098368000*z1*z8-192297843950906012103546726188734326794267650125077608915077359733753966708279743135911616061518806531792896000000*z2*z8+192505970608685831495968881394476318011413037247722306426731624501589823032758371170451876248947202134211603988480*z3*z8+6950970136760601129188128478363262890745926998314317473261301845043731131843125404369084483087967914237104173263994880*z5*z8-5781470560856582008060901385309042244880542226642829054546857971928410632489935319792776417325709298473305083584512000*z6*z8+24421200011065499349165535373854625479309279946895154573226978304417362614814550652132503133620880692717980414564948728872960*z7*z8-13527766989405819274203359966587681837000201620823569536205981765780595958254141932179251866078163967634253671852945529896960000*z8^2+34956734731384333535821659297350404261674145929396812495708569396840749628540936777067518079322684117302016000*z1-5829953730804343108766481179744828143063387937795701227334392487927957512195248350928848973992959539757774288*z2-17482197978341421209869599265891462335847129676328417897362005026335032661373310334547144505989585321038813660*z3-123498811495668981486008400552093706875484947847092143815603721002576591057360163827354774227586992835879680*z4-386521443695012826049287155579484081622072064462283334098271791663054690528696607087834439672206069146243337478481*z5+492872003022255246880878496217863385304799438174542705413320554798767212845888411948424061877917625845663973408000*z6-3307924711182046662128277496788182195601327230562584223735156510387059538367535725318715228753032996279445322134170428954912*z7-1169499575904019121127227093054220645865384771671488418714443873115320499353190084576308065762258615763799089679482880*z8-106350559327242420831591340638379303682727373712259371315048763135712522317191804860589622205711556699420635929519 msolve-0.6.5/input_files/bug-chgvar.ms000066400000000000000000000004061456710632100177430ustar00rootroot00000000000000x1, x2, x3, x4 0 -82*x3^3+37*x1*x4^2-96*x2*x4^2-8*x3^2-18*x1*x4+24*x4+49, 94*x1*x2^2+5*x2^2*x3+65*x2*x3*x4-16*x2*x4-11*x3*x4-72*x3-46, -47*x1*x2^2-28*x1^2*x3+34*x3^3-4*x3^2*x4+77*x1^2-60*x4^2+30, -33*x1*x2*x3-51*x1^2*x4+81*x2*x3*x4-27*x1^2+11*x2*x3+72*x3*x4+38 msolve-0.6.5/input_files/bug-empty-tracer.ms000066400000000000000000015112731456710632100211170ustar00rootroot00000000000000z1, z2, z3, z4, z5, z6, z7, z8, z9, z10 0 z8-15, z7-15, -2*z3*z4+z4^2+z5^2-z6^2-225, -z3^2+z5^2-225, -z1^2+z2^2+2*z1*z4-z4^2, -7781720731374955954550675507673901881244151200024337940433044635745733930993382951937403403742858301407672433534805689274460991508384753676019680728406909367265642541493155376956000*z2*z10^2-1752778293916862001220804306992280387548245141084215810963773769277886644225767915319674864414829052300440689836132401440434046390767445799892893906021325543690291738060859336430400*z5*z10^2+734977352401369896439809521264379642399234623217131627050941194916653762079353696458989284324605073282299025924885693844905909193851463019149110543480533137172460681872180225198350*z6*z10^2-49794152787831670561012816719880193375956339272200968516781063429777293073379606584688868452316491387825575638493054628872048123734303099705342233592275499225371938596614538988385000*z9*z10^2+2653024484813100501437769815085714949475120152668751585460281045484694354663687752468206912481941140818434565529399402077076240724104951739443090656825795066172770904893294927696765625*z10^3-1107442332414887191471968297314970810659861753898915339540418673944606104099918439197368810929377012106109142080697902774168011285283415162110270618061131655640901853852175056*z2^2+124443869531402231453843129010207765678109701717696895583804661510310900307838125783637368825540711780537423930718213925169572867378360725471149375428770816730195694584806650*z4^2+2705482608344290270473950397476550197950273442503683606606968800768295133701114281925617017548297685783064207280310043501743971752206981382492757661440063033626840672237378696*z2*z5+119009737672282211763005704214597813363682263706656899457088804579689989207232774478670880284261356390621353989068642727990513736600772495008401293034711924162906989514236130*z5^2-2887681867530931668827661595980599326122559029421729721884992170786519135207379981798566400820586526863734373122626832680656484926199757245076907260470270885129697354074702848*z2*z6-1220364162616112316205888330337005310537697152532795931765876090824358274305262958694696635398434309546739849948610952503373633822340548620032917892410334517936100165173883488*z5*z6-37121643847623658129809135930229060290069506168165034753082583085082839511237325264178762248352002330379119724928850856049353227317974071471328073022083191702506461605460602*z6^2-4365077475401777890832134678446338788179643337804880585403934706200479481096143787082440739224879309345556034212536114173924295048845402385081549687987036829853948044319726336*z2*z9-4765389061581721431839091084418139617859946514421280912841847947706423098042512324240976563219385159685079544032901989963010712736286506123275238190307608223353672063052583296*z5*z9-9514311739515472099585265365971516131446946856001568111869779655736114721556197216215732623784732680634306630584789969860112244195756731457575735944095917717562949495885291904*z6*z9-151175351543189088906696000767771280533911097765057253662711952886056467912790847443734306768643746785616781547504842750049373103928614685755280810806140929764315217920000*z9^2-81998555704078729198261441893460850984308977477606562663593117574619123965732598664332477381053842884250727385214245983571435514970052253857956898047057051639229261013091833786784*z2*z10-16217347471532189924500121735101795098113826661622150785807759551471861295894936361917524257309641067420883251641547604654407732889317033800750486720781558280872709544493053026908*z5*z10+11125813588203989327942517638631488828800258970458824204126020573233398635541297568437016439326711387367824608268028201224922036341773466073181342716203352676547390284251721288808*z6*z10-449256496819672720493384030199820944516316663281155661804370972335624120931305356424689898241448104236531944470069861060837782305604426440056243532595054190958751734830154084341200*z9*z10+34544367360934417083209725583068513100850110156848118826501222281314609048554324830382918666855968638340220040337201555426929264570920468253599376037851932709562581176924925672356000*z10^2-214109652107904792604693034081083165986149499263885483774312085253316831145211765898532076746818939042600480665812372699274464064294817564958278415264907541030508882660992739040*z2-38165571135353559694827522139711388861142903628071369542690453377281682121344499974503046011782056625688778794626558954813786817406729990519835914265550437936850482641088214788*z5+36343101952936393724191564105475330643848830799555748853717640995260118538656832768475013740537274016158696085490311094378315837928933021831497900003368677404430924754661831130*z6-1019567242556465579819985961777671185039503352921510497178215804030276335501327181030944956972250807864841489771503034561003521418569121158054746909631008948572138566150291943528*z9+157054103475133169897957104320015027629876698317875318428406697008802481383446845221644187317682546566919211751682613072709666731906169549138430317608937303261046051073513292711545*z10+274990981393198946095950388971989814708097270642502711935459731706876156407229124422175988515429723863540568865892151046520057554648958234783458226916687477574929919679650358188, 112056778531799365745529727310504187089915777280350466342235842754738568606304714507898609013897159540270483042901201925552238277720740452934683402489059494888625252597501437428166400000*z9^2*z10-3224261997623715961720372029758781114539381541065145375255949680968421805288003960384432784893530984205536445691743715918613401514294579126907741672398911113846747712976054213650413346094300*z5*z10^2-6153029141840869683086667895374275617237356439009527666150203708600143495514177836820099156977756009524675085451674160479886639640016034071022346355936195305818111666554936037532660667915800*z6*z10^2+163826219626383425657238352633411131596691870710060736880669453034984613892475196244841735493803724399753618449082268716270643656930330309272751348219050395913310296172442457387447497638405000*z9*z10^2-6716164256145090049643925162162107576091170245195089756705802547577169040501935831840705641208039356796063823019849196984762112187575162981137315909063581535785161716531171139069486591980078125*z10^3-1822472216347807184500945840379187572443821394403437018952529592970818882324851044454512423834577230759106322892556183583205746304629260310669418879623118036807303729269109947490428992*z2^2+6500856105581972812311320364793227961386670520182199283006899883539337243172097654446268399325488595217669514437978365899766158632785913496382118360090228636484279451865741560055231470*z4^2+9766391630132837822786689642095959422562796016303646027930743537756157823778749124981140144501381397840570476771713135757427516274019273273058052579004965134386831142375080218452332912*z2*z5+6717270166431131597223412869461115952552639897936773716049056339240090745798295325730101040678937745850774438607282734315964997831080989984432151195051721851211629211259244073756489190*z5^2-13073075171325955590782888808641347050929435213936969795729313111802273607434809278685312045534082781711825749235259211011008636673385486938079177646841295506172474143218652782247684096*z2*z6-5168306420898963421375340076439110317137687575841525885506406932316796631180827108197337731746573061556108371412586432893428564239120355931927636961750521148805778514876830568257894016*z5*z6-7496175947232480224575333418255438110752540391894737492587297662035146642849756979448817428141706492741768564413486257798646912789151927755048425733886729746208787889963157135476726254*z6^2-193117180249982308971542948677728737397825932927786795801565883079363550267074713789142984969965291684547581880934903028863762588248803623539380712859771006947672835363576791721997948032*z2*z9-50492841901332485937128526015812389367778795823733684067923029957792672930211787974332340935012893201129267861715260394986425259162102081643740639585004832098839067907616804230741401952*z5*z9+38105027340736899183967701759039676523442192714454437692345264729467775640770439466428110246813979704865768474543063323751060262088313940672445899425628594469871959259463717120054711072*z6*z9+498143059638674754699167536503105605003116837503207471247650723916825968549427359562877334622392232167174097370182451179665817808491524985647833610437806485585391535914041002684160000*z9^2+139866180714423488000194960964553744488737496225264264928699218432935624539553851486192801589150573490357092502494004628555949835153728986525654957805811785114118074947405440612330586002592*z2*z10-15648713845133495423106761723587442276908820174997741971968800313957887266794808742372710984501610647369548673730655073797760931865988976527035259071830338092116866234291268852691835753656*z5*z10-97193026198053505183431639449540515371491238812296053541255083343952372796575300743768099830577303793023167154631316947538653868552109944634952866405680908028349077323822618279400450956384*z6*z10+1278633448105390054508932687094225404608162461740880653248962948851089672765247209838487316540602162514175214650559164277382547258203197551685788010920408858903959943199057908672903185603600*z9*z10+53672895211132767400231740135978959145165395370716735303129306891959790017342322997557099895754119447153520930321488622038712097989812848457960697815220460978186913945101414401180775920477875*z10^2+607726217461017107807980599709000984356224372851168900143584582357431526922460871245435936756072387447383823930140629604354990898304160298503678304217388618342974614133996546599376063520*z2-11295873262972852729677123283983019399199606454098651113583661897682446058060211947552106326335325864804706717099830647267331005910488240183270843669841039502288681880801909078334403036*z5-300783887901927725720759432971980687209852579947369209141495508768665028258896171870982023017518953125037961025816521470265548881307745213164399765630213951219913947292154960058368655960*z6+2376581771182097586220824300522877401221849914850296489782159588765432249799715612460890355581636726987084731348253655389249040733621801320260671215874377757481171096371464864139167022344*z9+1547413379428019677701551562983912541880795487741236046295479950343742054199799357470068168608831732948447020426686466113876279821473558118104391717113099338652222059776895129991751848927345*z10+6647841101396967947183012902992484661310363162805259189491864119386152807145093442425447455750841677402882715674201030882553230087557073916222789220719849815904884205451045259021114744951, 3890860365687477977275337753836950940622075600012168970216522317872866965496691475968701701871429150703836216767402844637230495754192376838009840364203454683632821270746577688478000*z6*z9*z10+58363771508004817743124402467433254049700601976660913188712928078099045422504818903310378640018072517235310253810330475793568489966261564656949977961659436728718306835425418734882800*z5*z10^2+207734458189289390572059642008458430398417049530213983830995510524776897526859934503549528419816133282093503533192632689492257834689955610784281090736625934235617192490485615728084550*z6*z10^2-3609914676025274038758229391597971263649890434897748048224052487234992646051156249333405290891997849249491704713230063497143646738751495320193828670766757086118793863293904114295473750*z9*z10^2+1445122435604872830495593831388747594690881052708221293050424909656940896077027979600289472319517510979461248207838288924797365292426985479127908139545761260735942247922111671976364125000*z10^3+270049131856142472042517675080313721388300053130416778096044613768993069942035193057398181603326236807475519498891706557252815664112401925574641414664449081041188305048432298032*z2^2+220703093327704166932949744858307009663821607869883906538001043586100740741294370287056565666448094372652205553662966582748677914628374649179229572322982128375394030767193086050*z4^2+15236236684678720842387225476769440766967632254702133585067615570943861733106365865046781783719197500182824238315391323389305583427055563628297931952046545123749121802353676008*z2*z5+217821629762646510840605447242212214425056174950976535793981937786400169061869059317322005341400487374001083434069273340122430152996835176065770214572695050246288352714386776090*z5^2-24037707919245891578917058624383180852309258133709181548968374539019697989864940172647136592118295137421004600956878452525397327507558025238735820210063930021757138847586489344*z2*z6+5487542602396314719840696095737092500432358091171421524277780345058539316982341833694328994162898569215638364498242367806911216476415216594139054348562671097611969508182919456*z5*z6-206335613067779137976052002843059263575250264836424858622002280506592494854561217365761279647932179671764649734145658700095945067435957948208174429769880976854514662763939434466*z6^2-339546169757912588402562456863013724303985960226054126405393870746174392692956693201254327323988622878468420347657732350059838084146441660326951366094534509840335269628800040768*z2*z9+490867409485150379333036518287865044392454163911794509586512029877989000269236930453853687333562171862393829901695325152687430281397150371861657489347162499395598091002354721632*z5*z9+18144804384354425963682573690442662827188797108162880178151535589918796164934525045757708410486046793001818308051338098956977812564006614648543909805177822726656159827987307900048*z6*z9+9830144127842676284240207177611383831285187637304074289776757622785954398178149661602354963646089687435285212971447835903676618756515934959186538722701873573547391447040000*z9^2-3223130068890824604922593488386888547304397322011733088313536002490054969475349118961587413393149882712975005016990574724657775209853000911733421549558583697790066127301643647350592*z2*z10+341993991148255228824403562747532874404952570270221651584339658378755640552157736261172327288868296662950220053929705202417256005218132387347460740516930281461265448301352027390196*z5*z10+2919756606291117364449614718286594665137159087610543220767292860048528707175940665843828437597076407294606368163664191278895918793179811328994373775898589071187109066465984147639304*z6*z10-43796406369615384095247649357950983470296476305994823118123010692657173694957176559739967731763313615907831925359291295484958519253251503423053750373323800640547605100845888430205100*z9*z10+23051134265026866788333927647978145545107521403176578492307246239432706220544313934744062544779026792197989964535475819897945785132526425131763365762485787657769410231753397868371609875*z10^2-14745663562242104688016030473740072528238090696327655841570354222275487236422291634597600801191911679385966037269348957851895287119199926696563901451244467668187868677163268204000*z2+486014201288549450076397512096729028706204950499216952620241004609717047490976609815040295798437462868556181571980030955735262397037892095096546761025341227331230428287754463756*z5+9128348950418218252169317380912899648307037244819093130447673340256221733654021236741992951035025566767250393567288199922101001497311725087451939342422068702766111895043514198770*z6-122961808543045401458306547558499519891765359114187551513349648352269089031201264431600706757449052630557821703596083110219580213685547758999347703060115622824118258138714032103414*z9+140668508564755952074212162530500798188643328771456907641389092582414679008866836949139374160675528125382099265022790166140350048081459327610583253026317382216671249793130243095453910*z10+346052660822617131561769456296816319209120142032904755925344152685852547889127111528520477429595246368098876761386487762303780685491653177160925578987965797315261656372128132790709, 3890860365687477977275337753836950940622075600012168970216522317872866965496691475968701701871429150703836216767402844637230495754192376838009840364203454683632821270746577688478000*z5*z9*z10-72351544814116341618201443981696219552252674845526260428236392910433259166680572358773854176802891327435881338187118105585660374664819366620793450937668536636531376268846701748744100*z5*z10^2-353499728672879294078583516944358794647077064081277536004897615654759073375010476060871089413111627277824172442707472940474583206532280148445758507916384145487693923237142014353031350*z6*z10^2-2937182321378213438482145927358448171277845302506977855973091205615251411649327724346063093152278510952238842284827934835692465167084897950546233704186930500429282564574467138897752500*z9*z10^2-1351525001477018069226525830090732151651941303609560409832069948578346735969694973545012225910048037916871067772477513533237945410096646953199520501178451808575058667819256886549396453125*z10^3+438758155283866399569128049540057010366851843654618561828476848274752835364475578693249951291917652239722985658442671220560665286344291906901576708084060217887395979964240293456*z2^2+75132537573665674358144937527322901124810772329339756129496805358636488786378331221878883433720706967193020869285995649409908344428791578085372888404050356816667338182441913800*z4^2+605078242040251456641340820153165920860200451013333056640822836390361847131094821299312323908355015577894458571485982883943493041054589958523139425268392286324687216664011308744*z2*z5+89241708058044852385144548568914238000172409519103928602935083395493670949508446359249590175230972883683285332131569052963299384849212257243565353442411497904865520032842767000*z5^2-740142420643906177228562020624307575976997883704646756449787814166338398567681051459273124067882066532412385483828669960129966656099012942264881028497605873791911899971305034752*z2*z6-308805162300533694476506256494942634903352079767193476210021804911434960566772189458716509284179500979709068868512282302010517105064060126619270721963576672849437806887762711072*z5*z6-116041877395975905843229879339174734520335976426110868427509381952093402095820365277313985468539355839534070221611660305953330820555057924648281635968053709959643758741963378248*z6^2-1433466227211289824409783221155016628661341255008751745206909205124857584864974018430468782781739698304880686488702497003743043593210898297082763061623328289487038318825138585984*z2*z9+15801349218839643275179991001174766405475578015824461786816046507810497138634035127268215231660921073205992162999384404422338501795744406775333416359465115791477313963555232205936*z5*z9-3314685054820469658366870209089911457214023084371750580103636671424768011915614623263326389041517667943111151932213076047037577933084934818734702140904492074216226210831412291776*z6*z9-49929216990763683017824936567721856227661944317836542063400983348432514896683175708524399496591704955745225885834791464263759819714883441792682378631803207625576151572480000*z9^2+6719777913952721285297071926182340654126935493564293028059788271688463521249846593425038881676712775586153451800389058026876363483533194874992162144333377584430239727897927234011104*z2*z10-122952674877657741809777084911829423148568730244288595331047057789810687459328961632655397704403422046595745757416248250889710423909546101180036860105918519006637175544687952970652*z5*z10-5271241125820773107620973081384371809031671565200585513711201439312557147139254520614141704500543066059557332545799910072855357009632652918202424977169184558966814251023665664656648*z6*z10-24294694772983644141423480365609284752345566411054238599442204550473043048449855343913900059068034726135079283907169732465901441732318257070760681459818637003282689785878042068877800*z9*z10-15359480142374911002198661832994643514246889417129908943177796712727409942701223723328143725072631543206779866560412858964579100246290068054223413702766400606975022720039625347543453500*z10^2+31117631315387667409019627691789336788876158832084751730740226892791325056141797267467390589894616082616376795837761627520314217895117107961849210785523427143633758779356873666880*z2+878857847107371076839565061781028151124987724614126813478439745104904337259291761480156207086924547670510636367088774949679953119536776286060070160877436091146434657031024925088*z5-16613269969391574062902050356488095446010181588604136790310113538722762428304233283585650338226103543255464309998328283580855874480222018098534551114757076090660212242386955997010*z6-52015019816230979945124778089832029690570144658352921553394939313192694416913459552315106234243613822749401404885095428331428517430648083402627113917071311485493154807991129036532*z9-48398269707905390988454922638635435376698331202747210572240040039912025025562259748735717398403190030934556311834027431144584522904503053816833976009804093586483428591707188669151245*z10-14095704740543905115037209570063823724978446389839610928609474982053718348847411325272058431809877145147624550433024852800685204208088179250061641822460589312207248370584939440798, 3112688292549982381820270203069560752497660480009735176173217854298293572397353180774961361497143320563068973413922275709784396603353901470407872291362763746906257016597262150782400*z2*z9*z10+18988223254976675000654851862816006905588251791995232708256564741332819817051144215990414964787597341600880045780203477013963646451720927526251784681761240041789732862595864453354800*z5*z10^2+62590278885846742914640815694583162231746801404930893576079560423804816266583323795114755583402804794337355588461154546803840864169397159215223231166308923304976873936370593374665550*z6*z10^2-1052964628541052602253215166237587347443661352426350479631107889285883092773708156072001113417871361463146240890608339998821623240191810363195622313916894125565253978935032762379778750*z9*z10^2+415525572262850600289828598476843639008195001306749096982152889028226652676853105317998051580862147179145340715047561241805017349280152015104279492856546963205412401376158681813817875000*z10^3+58913086127665844507130978517308440000909724276877588431273341279164375414849323591490939093228398938335550212672471267098034167881376956955219543455311794612937706516373811824*z2^2+57626582922920526324045880525049040724351451080978683600330688342616141743068596867644615527165536168433420318587093842689905810869580109396043776564816371344639072297025963130*z4^2+7448382926178246636495089903640163198994232024360461948715770898818860389014868675990845835215559879856523207634304081194369883247160191605010924960971762781515598107364204232*z2*z5+56600166551524963218437216251296200515113151134627016089472838539410242338881195088573816252257778668773238359874978551667757466230586384240433793160692585448213283085455692754*z5^2-9122276294774609271482869876009028348906930081309426214858779217567738146551787185895315461148521159661201632290163226410631992062386476107459879935013055704530704015079113728*z2*z6+573204090336166776427669085335821558000615699816016092584978966918858739140702826233752573817961908388475703305483645505433064267964640087329085090323691823072016751859655328*z5*z6-53076969109680373924434706193962392347136305330638602374952740144777587666051086145901305783436732760050033297034451345970538053172938134218644297853496339875342819484631262714*z6^2+13851909601451468335504151024931048128957367288935149135755288546954689159593808590125418307947019466571332005529509871650312203980700835239958341956135850169835383253736812959616*z2*z9+124689635701053107494256205499860965871592710397699546727578781213318495734001125884718585126773160787829243148093332913382417063073288498361399762247391276092083122331303496160*z5*z9+222123063148330432034754920893120364914593837534740875036405527788944103576551482139320556931248499275177349773019979311634543508083037525263128385635736227607980178694954763744*z6*z9+2827464194934497324161022297394569702263893298213134271874963544666478102329228429662467429997226019792835885581458489789499368014247327894583349044520757234525234278400000*z9^2-990988366308429845339746906022470360232196364552230023123112938136439086928488807471030145935925037912333260462091055550124700619168744802949484095495040124445956401587582070627136*z2*z10+108764833335615911363717451293476301249519692235114576820746190762116335560966790807337542098328501121172533787570605156537266368186398668075307914957100111595856678043478082641508*z5*z10+883884136975490651663905216668685546570461749194871331004039598470348616136839662990097143182213795562968695284185515309899511008113955314094960971167156003824083009476644711773032*z6*z10-11627316119460498525189582838536405811011383176684741584034178107195849810596161024215278002770668093063297448275414440264329203670624719654826098767330230315486514285912820038379900*z9*z10+6511060065084834372651892808284284027368240481827984567347801260495339150097859392263097851490076601030511257213922626523385422487370959437251783814528780606177238184729517785749706375*z10^2-4552561134322600716759429338507975095851151780157646396949907083321736472087755957282928029101823594678543674081227818739394055811461333876040159628573248784783049542959586224224*z2+134855130916298253209137156801517084251319237876086592342723341700778950310865249598623489673861757148934323824692814463115180040952116913510163172315349446402145264329712981916*z5+2772587544112908610378457275373955318339530098698446903354102989436538894036098624477981115739348621354861220767518759482195619699283401194970195521932971892350864776104304645642*z6-30764312746620598368171218811578999946904931712122809211108266075587068100722421322474455276808488392189394912200080684106769739364540031108409541869827385168551143511640490205662*z9+38794111489569774886856240930784820387697151182285389185935748406266218656904694441899643596439155325530322408355289201185349745152362693490824404117912531914759455100170784180941390*z10+93162218017999048380244344090583218625520155081810274245327694150378241503469638709561821330979863850371225587301402742903695698928747312413814636681861299755681628195411217857889, -553366807564441312323603591656810800444028529779508475764127618541918857315085009915548686488381034766767817495808404570628337173929582483628066185131157999450001247395068826805760*z6^2*z10-11214717464421652872053934609343574988033891837700537964177694170720074521529156059524100552342324304480565712953862611028361352370162812186020826476654365281142221382664871237848563600*z5*z10^2-18263509944726447070008338689949089378525331241875232867772059297779690611611914214072171125138179463639765982983577769080442537701767681928066144189453701582214194707409146355489608350*z6*z10^2+566118163663379295630294147423320821125428335767175907328643743656130600926176921872796812012266781727844026415397845179968564172425674050960147184715318139236500383512655772223885000*z9*z10^2-51802234140010219417797557981005085570742693876392297834951472028919387817420991761469136081180747515200192674735112455454241649098770378943884019662925945418945609712243404357606819109375*z10^3-2478513828407607291547910123251142376747128226648173530159882115596180083191538259393210923784687418379034974662477607107888804211724554138372030290934221187040760262329591787024*z2^2+1213633355380847961269204797050367513632494267840809392186954408938153443308083881123579866014577555468062387582439744711710714879342928346806264306726463045308925621489208235690*z4^2+17794193932585826559324130051264796060801184985323529319324453720755373486248103166398826107473507174739559895409305446485704682534182074943214164585144939498699122933405364860984*z2*z5+1628292127111086116500772572721004747907604581691713977780889001115001267625725181428698510790922356364930926833134948727289730243264099690392089883540615799752930425849658936530*z5^2-24474436153258473786013099949617225009803258343142490630152316472681049376889048277181432578433999413149686120768096464961016270805359445718193787537546895534249432399284435223552*z2*z6-9406101642827807109568907032715702117803350993372836478129240853688515216742081417973195588474407674616618352292713527784245219043319793629639015911663153126262704347012566531872*z5*z6-6453495946508091799277264027722278204301396825243551356546235316438399977488857561549393707811914640627460047372907573920975143964582018871587242492919935429275485955488371791658*z6^2-53900551434893258020467135733489987601545196147601249779287416952615835404194586991148249698735921450358108761279928974810696412440428977838022099658612942927978876451678954436864*z2*z9-48498167087428543117158488406111002462427783613209710900134110511516651061589310194536777543023239113945692168947969993376386861760940997307322864291297453703875532650747112482944*z5*z9-98753014467169145397031973058831294544139189318567058688192722393036108068425093965779466293519601212803886438466125670021560519711060395895616641121689818984950721567316553422976*z6*z9-1599679145261602626424449433716790884543672158363458369433529949015203340851820714546471683351461179018245572978849802567218907029918654756153302331478066525080755785646080000*z9^2+250766182202387639652301299755732723429377302374249842476992760458595856311539536159590061704259178410846414674060045468639945389627337224120574422935215897100697006518342831481202624*z2*z10-76126794651057798110145128366873854041756272522334242388273486106797629709007436959273548982584571332656664753580777338722313304717637279231316667884561992200192363124851167878438252*z5*z10-234707278636547768695681970585573116796595714454409015314900393116463177118933430918101307773706549225134437722502169278104658564038174397177966635060812994163702387798879367460304448*z6*z10-184306201387755270108521480715624082018575690437565906366084216080967418729934041222607097953499159808606678565985918370819663202115583146827956197648492879249844472337169797837298800*z9*z10-644523440572137160912601345604860574912565638613048606277223813354027391077478270908273197273625425872448557031908748636712497796557568405565583522509171312588133052795960513733600311000*z10^2+1095996693992079884337705411687500348450070030373067700755274808188866094915230892682423521287293577562205233764185808758194302128091246431690470668424717324565698876838837614097440*z2-129919395512411613431128386515874864651137853024156504094121839164290699639397340506632497080351745890302602608753036829156441794679330697990289391450689202455420327811299193697092*z5-665645672950343825672542194178932231288919270319022759387967803158290782834420127194109590544448068534105297518617389134823035583066783258638307243589434256915103082516532750835730*z6-899069411464410578416873676592852921580393114192039907140937829904630516900077039446604602372776519708807327714479055385447680633515573812323951050906836183496356411416366085146552*z9-2493576002034470930237317830680755118341897538327415051556816444843722840165655205616487793808094587939579012341605719120209982927788540989376058022555629062153862620816947977765091055*z10-2699827888834039347528289096279780069042608960286787775079925843140045442513027847578435983586721972291856405229761720716257505226701139022259276592172574888479363549846618138675468, 69170850945555164040450448957101350055503566222438559470515952317739857164385626239443585811047629345845977186976050571328542146741197810453508273141394749931250155924383603350720*z5*z6*z10+942552007310979398903933040137487587609237777752881565665432807814366845913125743774510129413112269429363349000019187303651026932312447260572172980797555215434755715697062689789717700*z5*z10^2+886419122163250268756352567403298458064370684488486378394865149270010317885316799458361143874605135181081131475547434243504030460192279437757646231219766210824401032518954087304492700*z6*z10^2-6240611020845546930156777675075335560734789031033756854839127137250430097295874778548312011316843434517468034259056209822592626257463516346767117026592278217583678811600845727648870000*z9*z10^2+4005231201729301914698577820187670049176565845367272469419757089255441112159167859436567327761658498618347180856142624273876522324358323666627061478199621950511159113374478229163959515625*z10^3+1313353427493494129340902514047720549985499834388928457181990197887918021299349313403145024182300076159411100675693306347871471212231890451952731834232186966058632894085403359808*z2^2+118705946791274698889789145593192643571775252462521968760806664688712831609568820488866464118922183356489904683161624605413126226944919535004243970829426529831497472989181281810*z4^2-1575977188346682935393762836618184642716815499819626304618612829419376213719472821886463822389699433135467956923888976383464924398569179519419643146769882654719681944916634662048*z2*z5+97165189705715068618577513096597206278739342327080308909984260280680608722999348582963988279661144508901291215206125598040578951610549578749569400592965593252053918551919084890*z5^2+1510774109153413556444165005195861656117553863063258998135916418633191388396724144234995800059497597230722270604117205897599384605659762174920477145218764816904172871488233749504*z2*z6+1117678497549326615533047479563436781723533615114109250401150628857039704309505678901581122681456115586384568349465001975703685193875163591969767594380016382267934317912912275264*z5*z6-11512881902595466100521445800035159226480588363202072587438926299469530493734662404587718988801754372511662127514497893293272001307543308801389986346626236549304722583369159954*z6^2+3647261099520645182355208257335990612973180929037767272383231743280412240735721212739764119823278296999140583974009462443803020699991538864627769407284977464087395462547986626048*z2*z9+3257985003164428706925616565216230896621587209719569893202006802946387215510996655237706872850960451784122298282198053978813118033605003835290025630179140883970890124797332235008*z5*z9+6596614394100352102723084552802388695295835737175750797532100066897579858258638005759902374864666418863261021918964885087142446320574959540813186638028911147985479707902256349952*z6*z9+107375396504945971144369712592778856309069587456675769924923675009061298789343929381568804176067319958319473996576683634687472777646279774020428690657010175304956782018560000*z9^2-19102930845969318881066242837249015217069699701359312794711313015798304963616225933893488158987234343531067523098948374587184369990102554976743869416124794493495190058182319648671648*z2*z10+6088789576664051654499131469653090006466638917077208399464077875760644110958103214579764877022027397611181759560876893615797229529296234117783035208568502510555053735410708843773904*z5*z10+13148953133297500417624835492389586161625396661981258013648438629942319920198507408807172752185648030934803039162287610001078338616459547636050494707404256603500127273623225783062576*z6*z10-42611886861711350046755322243133144377788281460533722992184073996535672222395324664173221817345379413443519649564714122114003663537898623674555118191553918982962198436208590462898400*z9*z10+56319341567539165468327734297301984622683240151899670546896088640167273016207509102028333688650616743576119134262170476084823258376210874849659838921681327665650835041973384368041838125*z10^2-80992536715487892316841437669009582999339401117329769238256524403523401231204013927659002475901541630085294784406371717045125267946329129035894335502871355537916862103026094473120*z2+9179666195909249981158708648207730951551637046390945637628525425241625003638287632912748121754518398103645257660787800061739552164357975781957254180961520607213673772854818344444*z5+38990316160231390372274064303644138150100096103195499868347700787379559258174708470969989596700168964916228630160353944630344366771336672382245815210466196732850691749517814790020*z6-61494313419178920444985982560477668083732723695892397805860548946111461193857437204731460334638380463519538039434278303613209286937627177377660007050041173013063600925261273794416*z9+271267269746955766212785531839127077391005402767288944674068847624475487743376390729558048563141907175733502098939522239072895890597523296918477624542863985371228714565335126277351155*z10+478429081518126770579911410780055104461437485192044037467756332292175935737174357036248679563699993911806047678409586921701394559264646921514823757239638944769163971131536163244321, -110673361512888262464720718331362160088805705955901695152825523708383771463017001983109737297676206953353563499161680914125667434785916496725613237026231599890000249479013765361152*z2*z6*z10+402551313070398337230587164052878633718210999603909821480861115104888394274560133063829492059803714545519729166531085732805275464067148155066636684320688490340612634206092969786137600*z5*z10^2+287592019425836136271203233776380208163550687757735199825039376524697377575148923953518779406273251628357349674892483160972309137467507756733870700166691839541342945446166173006752050*z6*z10^2-915915171048766371786961602604253615372174761500578199978929991940589248465074991368180827967941967837355464132244787758618605466580095952706141557904597298057692119481574799996295000*z9*z10^2+1469985186401391346742397415685126235106516032613670890500335573253583552904192449407195327141987057943725745792280580377790992600922004346062595031548488827215606509377241955251393659375*z10^3+688520702264192909197058208227128478548813822632584989533834133909807162258505002256945669520840867843358750427474231475455617882032574057341341205042730386473996660336926703568*z2^2+81372418686181761046707328330867418525243997425242015227552648107445191167183183246462393382638830035793739891151595353951820065503380528401383297049189346767452234919811719510*z4^2-692589382358426300345361176803068872926908142913546013014321825594033388907123064838955313724074829079816474017465446158272397875636996352746782987709011343176344239545348026888*z2*z5+73849846989962469729675026775811926839659274423771024671328964393742629772694800000971201884511798692006372517841437443047533222193349861557667408091268807124467779440691956910*z5^2+51731143306119901830284225056183245434135773042308041894157976799183720860445329011841278854001721722789618740087504246129224264600226625105445566910537441083475112675792651264*z2*z6+346090107917186934598025826861946368664184802404551358645423060506041611544068552132224994560704029223692749611968955406410952447059006212212502899364765155597555977218236348896*z5*z6-50150249615350468739653800034897925281821392750879024101852717147354924895390945985736612612414680856447139277087150667654450717149059851133279893496102038397909640134149379030*z6^2+1392245053247004443539952162398500000588854225443606461391179863771735823370407629442369256676827231466939034860676505735945638189297379246224219585140010009733845068409244812032*z2*z9+1272390968901626781641217643907651452688168095224833000469279766804744443903532033286815996673984464881548549583250828402736937497794568462572034197149432688173949122232815478144*z5*z9+2572151050785120021854935167674147469646994308757490901204960776134823785115251903448132222484146218987269097976840638128489242712646403346399446115911676324604859966874060567936*z6*z9+41744607525372897691990309851355812733003643767749172027812378924698855111392242503067753773811891326588641339247624245841468812809461894573533843039238883651048293253120000*z9^2-5905038252630494197817640085832149493142086957085780666145135685337754282233616067890523640628794398619560803149275913001080418786202644452208877664579965573902858920179844779236512*z2*z10+2814533164390787718746376699902001830710082878054232258243307078877428548493606891579624326534901728754449621531288954728668549013016791493939752672086265009085104800303161653333308*z5*z10+4177803123454133556068982970982112395660050820362677248075364321462149866397792255451281839064269496248058139260754584662072872446566315650714315392525461601365281870597839048483224*z6*z10-3531826014448624299946499265026229231537281691611793708524942432880159799522570231541526404281196546518287279340644826352956981901005200510252482327229612965323765270261014257626800*z9*z10+21921439417166130652174664278171983487143719721821545346642358555052153796728206537557987222415919735671003552695631172583099535398965519365759796854537022946323355541948668056393534200*z10^2-24604470833460016677302846046539733499583040786241540460100024187876008415180377107943277968748121601889445685774580094637803626470632243099153825775418123031418744442164705863936*z2+4796147511142069795739985062109651480501391720729779777736676031972072895768396746866817199672712924274605675661096218200191683065153050092215935966690250194460373201688936543972*z5+12209591439136466569202911012948947286900837722261958381224635001119382408143689569842768818600678646725501754081267895884747381064385415329017762738354361450685769115459717272166*z6+4189808443784198598203050746595550980327700568776144035018822110340211561752992378495148064020456110775279329940483267846298523294440148557079993078957494820684707401976055540264*z9+114718303583258552005879050445509582736488550664552638538311740617847472695093579370297928520890318776614549929598722644027484230745448863793803504349545791197372391488626065075005151*z10+226576324165219740628603154469601206113392837982643420897664388059238146408515723192182593531647221852688560913290194631614657902810426482957158653611665146671409971355235469912844, 1729271273638879101011261223927533751387589155560963986762898807943496429109640655986089645276190733646149429674401264283213553668529945261337706828534868748281253898109590083768*z5^2*z10-6457403833634355740314664708705133418733931984311073047128203565292044035851515692335569885278416559579412768141624136002354571628914213267343931512082852431301752044126970611218500*z5*z10^2-13862836579835718059701727588435835021741580669411282070445793839022541745037584809334048673528041200481283288857132330206078050265925172058527522767891652663645777563106627814684700*z6*z10^2+333143242583550892907126767732003457345705439403430088185389403971547639607713149480909715088259588531132717942493382852390550032441777084661183094667592091798112856007876451458610000*z9*z10^2-63137043443190745713350135297086514656730629414702758668566510719366637937446763124424096768615605749834235414959072897882903242801399974698234721148205307084911979985666116854845190625*z10^3-12223725321000785987835046046130034583382923016792648794747345879110709271893497420097837818917110233063802381794321392358263877419675497689213504691182596354558420175170016992*z2^2-4078989233982038644789000377367629494257262187311348805659527408987389711882174116516258967876582429243190530554508492705675715860810373868024731453022595009575067609274604002*z4^2+2399852813219317165314575166230460832607785487026424977207173331873687597686184094257403976012213431063074647569585378878406648328868182808744372321465124359509575463238133280*z2*z5+3866872124982029087071325481540121620928803856783793487126933768901302709333953718337000667646081458256665013145529052786610673632383633826184438796123533370778427486664344662*z5^2-4309496943603399173413167566698725816454110801878933173951004021083609002270467773143301851992418336351475733696299509609096568819700168178850239529586707359735445612455247872*z2*z6-2275450069558509624029184827191678185207044455019402179138804294206009345824067410230985790759051105167401891968691803175794332502465194649875652610374386404617719349902369088*z5*z6+2335536629089220303504247011265101799172766955127143275807558159740155327110114233546415268937667029490486926957724702288518896054848160078563225571170740437505687648213756130*z6^2-26554091655029602859922361636180574770049675238210694614940816565197501994678290980956841296469973798472909160905141306600935614014943380879906875489975696067285139240306831872*z2*z9-21469884195671658890605927126981608624416368780534494195575548695531299405222015808175067224693313454383421530200996882871182702701178962495850196071997845100228318841773150464*z5*z9-43748139006328287526778798319987946935671672005783797910830069504048561135005888670434062815608399947119425171584205639618288377810048950069867812542697465521356284418531488000*z6*z9-721487877704492468542217944251466776610539162833122727802209829047766418913507547641132912748194393988774898571451086160153691648199896354573949857912693903576991170560000*z9^2+293842552568157274253686136844210166182480467808126632110965882974125541864217021794898261093479744944204833444362671776273639564201301582264416301828147554213930206920814619695776*z2*z10-24249126408816993279218669794573605382346785936151928593721314979991354110375272812125806433920666586369798919315805095430935463519271516004350057450999167309513768894658425736080*z5*z10-208887311594433051826654909714321015446561059199785485705980185621330809390410997616310355594746574644430116074444665132661674322197071170766401502838756324839422842504118674586512*z6*z10+2850537076516439696359967641194992415314020598134599324291206259214003414111538907198200148426385716731188166867050767286225211151117506594916187051628075019161111500615873131338400*z9*z10-877265921477907721657071311922769601168029401079916816829009208282415711928743012844033899183345129272610681656274268561632969968916723713827704582940127316207313374286180696368469075*z10^2+1268351626877137303103932307242119770468194163524520325198874086119665796882351928299428118507064157022676907801819497328325047342491156578352686246628391027765694952862275313696*z2+7077972178775381195119867947528532262123326964976843405605387302861601884178705658401902539660233501718474931713830910330010664837850015344580360289173223327029583455261794436*z5-631811002438207768056532855575595013725234249449902467488119281114728379598596139921644115577483313451192133305340966924253300974910184471110696067171597507649536800067504043748*z6+6057298436301432747080625601949078754059743137261273280419515477547148604346788876634994136663198888275571662127878096944667661285802882068224652426521263872399766731674951757392*z9-4388752963810934501362116813793134952219877471853195930698481944249877818275901914070321587138561799956099904962882082659902577155135342446185007159099971458875234372808282346733431*z10-8723824909357488418886549972296579528285687407351340119212307845600463800961744130396712786003661593675745892223901982387755126080657344241281239987972941276472174996914321987591, 361998413221820632094930223959909313319151734131410334285269899049167985162845547198281611460776495209118553450*z3*z5*z10+1186162066332243078433218283177411918369599774331573710898518744791265837649140209793570429808612135652333805300*z4*z5*z10-4519929332360965277922957799122815613805760377854786909537988826271469728069892099004647025801013588229892400*z1*z6*z10+273626820060114602722546751119301918151706182629267636515336476654870112285596064241679292400544296378221331950*z3*z6*z10+844638055406819100056681946720338758033286511987077241519601075964673829743107267703907715750281243265495710800*z4*z6*z10-263512741113176272353389189338626733715296378393705549993191793909709896624309890507280833696489752115885720000*z1*z9*z10-16900680384866474741902127765773105630030171123165734740657696679608458154360818135586073395198411836669729568400*z3*z9*z10+17310782359040111410926054216598510261738362820967883005004740992484641453076135366677781312667432891012485250000*z4*z9*z10+350769394775909935025485024565054886834146587688578566245015007120670359239014142286189143257507758429047692265625*z1*z10^2-2564032294396564068347108723030438763790655191061825216103169703049159424357595309564246055241412425898217005390625*z3*z10^2+121341859743710692868972341158270200363163345109402629516579904862038245145465297233982684687174868517082048998750*z4*z10^2-1893135253141210671352932908312214543161877069856314262126538491832822156483856976753114487611843252605632400*z1*z2+12987327267706827881901857552150633531151697403244847181217423325986562306853706325810646814627858245416009248*z2*z3-10335739478382342016289145664757490339190247043573979572413972923388901530969177190692516019236487154783313424*z2*z4+3046744616259109648621555270471570944754461451857461880507366332609538528421170997070042821965059815738653112*z1*z5+4077774458208489088867860299773255472893093152154760740744994267514697798049542730711639546126346320553453712*z3*z5-318141878102828040924400836529161015570356115468265000136262457375923664487511131277629072937596455889814900*z4*z5+3820835621715677027941789372796987389153501858829020258694899533570508181451329082189811956342671300293510912*z1*z6-3070475119908373414011659562021174362972855470053943771871619988820166049058483196466918958396858809698918112*z3*z6+3991851104888857048498940492098140517271749363692775490823682495942867261692661963143243648490468039801827712*z4*z6+753809894884657289392697244670197856826347914000738210088864963620744099019011668691450093989463759558062400*z1*z9-78162826929489454522869737843459242684425419204884713538052075532548336267453866257215065007323549805539597200*z3*z9+78063222065519149848469066398633253615648262040855749293497721218786096669300729749960768810043385550189096400*z4*z9+3119560346795736433205027447441092752345986686204733139608155309258354425831163687227661476063909075326100643350*z1*z10-31127618370990444036817454022791238351769526649589705371671723553286357690261796531999630181705536846507975853900*z3*z10+11613987741543105250193640998285933061171472021055507720249274216424882120229793808155483331747176253902147684750*z4*z10+6303095296601371203834691848520775032928294407511204851249968937384200374613882930132679274915297723952895725*z1-72961384011759368790360297173057365718178961220070339509019163893311138781200131305551338593615331257826878327*z3+34481372739483450584409032477544501930237335216206597642864294434781613992278527669315456072503164435681843276*z4, 6917085094555516404045044895710135005550356622243855947051595231773985716438562623944358581104762934584597718697605057132854214674119781045350827314139474993125015592438360335072*z2*z5*z10-1493402115082891502085487350599174358046762247291644474791170183571229961617010041148455080145308806990944258084528548246158221630576179893501302780214042296417380631178541288183000*z5*z10^2-4533618208774099293681326480623259460608584391012116945663823116157106111573723380455506339133711865176099714916501510778302053392534011188994648598610930337719586920463085177168150*z6*z10^2-144398553363881866083720994629053741291425076303156034872397724166337504663282942753048287718562505510525606682346552140601930157720839243722114987396798504470926182314128339004145000*z9*z10^2+1510109742677404993398195164169894176529619572939265738548162858160739871024672346493121317327996972760114646193811906627686131473725098360263059492177424821647919010589126513770946875*z10^3+3463631890443820144632082843568943371653935788331447317379035789215535135654024683054066914551144811458096254172450056635123853465510117857285182711131288970585140600250562768*z2^2+8889150469401698848606259297440854206245339414688514442932019101884448340294023137029642778485553438819353615542137698977388817022687099218037222357098668134384751258361468722*z4^2+44060348993524240958164260028626666162677508141416850557361802581518520564167780460398175876734240855253029707084140553911035118041272504578945127833311061515085785767942054776*z2*z5+9233809201131635879039366932936441017279095184791045418905966539118932549434374671918198317605819838951083540703955363337871041232691770576132347695799323274293144390605874522*z5^2-16867053227525851021366982223927763894575211707137133262102796518858933088341608858346860526862564851011302693893106508655187171104158564875843705504774260458227208422536756224*z2*z6-6570123822827543744709395103274796125638800490119978715801438895841157110652592032446831370561060517463239917031581599530755967545938043205024427479555200693505803247606292256*z5*z6-9574059620346194528240001972715594318462554714823545737523866965963445324419852983851834512712083451948289627546553485562611995563112435542675640493405260516151068366651973554*z6^2-33321367761021971995050784775142430585501689611003738181052321635473812552756280803272501449776673715682096301012691283540521972367693868972181349969978378766949857249857096448*z2*z9-27469896361547966866149384165806895497328591721419369717660938001840441262221834120483696068108443537552761631001811307652293679621423214068868128727049565442193393925206411648*z5*z9-57081882867924906978085069701547609476271006584245033772442136613282192710953084151392585330956579873659302953511363539954626538208643493314519108199400761548932780305714616704*z6*z9-929262800595081582632020425541462140599899546672761123704501139900119073743228698115464288457409468818664386245874155770845999876432077290333989312532262733372756705280000*z9^2+85747874079866815456582284614744426100267547800438611013842741395450212222108047549629508919959360169300767518214150791199339113809064511229505959793501009467730686789407184288512*z2*z10-9983129674778152619892971946632832695931242363686199704063773907209412664805356796964675657309814575169988860789131680366340860865523050651329998626711639523714727251826580781492*z5*z10-68112892263383704261342522223332199088253053084681660505822698327867104725366128824766198827913175833966430098762017767266902071478100207578502913512591844210865423852301224468744*z6*z10-1438612948694563928006546415158153770060805710858244129029897001252621912668751306492754522908041507964730883718047546996140141778033631401511561925918024165410216572432882592110800*z9*z10+196035433246139083122105327336725945104775981161799599804261025789108641017115547370343184932370685858151253596377401317944442146381845955243509868465759861045009428332988964792839100*z10^2+397446326937706731569764818219847221299439391645127369167866002734746629899849394662265216842258472311929359615751968057095173250885780215430646375606241446051257802387086021152*z2-18295895521688854988839644161263596297793955932054177798832368910139091355258730202887058211442458270262218799287627171561638956537796465298704316274623887218149220636332096852*z5-221697208381556750783044847745309031041208108077157856403735635615374597670159508665113803072853165547887377850529326184266184214920882531772153927887568566388114517833571244018*z6-3581542716111369282194833993358859602158878159612007207143762020420847907485807512104403737422416477684124962982357042850922757271987927310813072453498847041815350099457823883496*z9+2548008439918657668618570114920282811142155052881300061235077117013186778282743619426984114598057081502209058115020224642318394217063405424043359185029216397946407856193992100743419*z10+9571280022837465212120280654431093251194520986475778618265710913505663831294196535790584873767776932432806411211738814946277537987928320947453813968855588866967572162805813669324, -6294428409101017150866646734214903139993410353076962892552273004666932926011558374683720660079981698696153407388600*z1*z5*z10+31333620122418817544696980964993271619263380046448970509487478932443176306782816962204144133723264100236726336588175*z4*z5*z10-10512785802991889473882488323486626425907322680395453256864901979945486648231917627639398911503216127980058807514800*z1*z6*z10-8171833696453622364352188983999888836073640946023506781828799131027050061924810472281227572181188030432865966227800*z3*z6*z10+29736141838699142125115325105321773807281987517907985780543796258509481074676209449146743699878344045156687117919450*z4*z6*z10+47506417577237591675678910741306925297097123510867698885797170388267654668366006348609334272822358604833280606080000*z1*z9*z10+53555855789184104417914598143330435857209292802892411299850397298387678855436640505668836866043579451254329997124000*z3*z9*z10-101614977479384173435703535126718607069312071633193206472710068429770871027618474452425848979006413354489731518020000*z4*z9*z10-10601939056121328646018269684757867483167542815383479975817724858332841722077692078445720033056780266022711046808046875*z1*z10^2+9532042330932507010042789790248749823069138430980478532607437663160146849614441857419720012545380267129495644637968750*z3*z10^2-2345674824338561846191954787101344084209856111215771778119344711414315185990177474708329968974443494081679254410991875*z4*z10^2-13822808777562058539995117462026815651560071805300904321737468254248626288210606496299250324862362268291178302200*z1*z2+254298687758146955557692103375436178711103590595815282396487108764972833796780311867844920230930357562058461271268*z2*z3-235492631466596810751934833975285331270929474137877096523004805594325416408741940120725325399498060420682467321484*z2*z4+28635144929101557079754490820108560291623129067671538361881289331040930164827342796643459314922114449045098981492*z1*z5+54018932964887266777545569300702919527842226515368017400352376766188801253597733758567042234720710609092593087442*z3*z5+28483381252890480306086383656205169373070776375276601185277375783139068774165380420506224773946896223898687900025*z4*z5+820440194361622130044476322744362057749092199438104380174200093912497423196602352205424425722377343675259431242*z1*z6-127425365370531023836891011172900197333867679939933274675051267863525690083146158152777167339542529195793805013242*z3*z6+173781599490763929206123932824431079078221104993077780963071935340857092429939418246521472827869335598637557375242*z4*z6+204666828465416464979516488590378260063857597118219754742252476938735185846748914477887705082577844336295827072000*z1*z9+248565934799687145549997472942599344257574677594157957151188327825506904205395943064135838446308184553946769680800*z3*z9-455699052237640813855798106905660511992664052974443867049198887591031314511442799859154613538106010626078808644000*z4*z9-74396877602493193637257987808318023875653938830261073814100270801466538668369617177573381673871489456930840999908950*z1*z10+96301791579297291124589633851009391869677269697387290102830612064975504764366976747275302473061633555337549546937700*z3*z10-8654728886380782727551069642471062098655671425639287375863036347074744059905190719288732178394080033793484219812850*z4*z10-87579944970021329080928982018164639753158801377867693146342700854230526103586082911234164607174762046073516501675*z1+530441234601573303045598436671204300467089615602314393125464091395998791371561405515015108897108008977855762588618*z3-315342655188330037972217498245041022398063040076891321196188445749466564572732035793649012277474032288636986823059*z4, -553366807564441312323603591656810800444028529779508475764127618541918857315085009915548686488381034766767817495808404570628337173929582483628066185131157999450001247395068826805760*z4^2*z10-13281086691184646708954627316129217682028750072680081339258719311613528613001641081071482915631417603545977798759182334549114815291415360431570884560520878059158782036785501833438483600*z5*z10^2-22699617650273876849112891518248556585482637056086843130314713326266903970023941353059066700667152647793776635417860114746387513786863736986794951475179030434580843527603267256188712350*z6*z10^2+107171955790399665025910859821664427171751168944864804126653253014551375275394384755763905640255335111690313768013280357944944574553794341142538737478344787514632614306033120238979085000*z9*z10^2-72006088041831258046069601276072770260896495289097180608892755459116711957403955961284847047137741355147148007522015782776770686795218370847319130430351643686117443307656561751157280109375*z10^3-6390105931127858807655124858012753443429663592021821144479032796911607050197457433824519025838162692959451736836660452662533244986020713398920351792112652020499454718383997224464*z2^2-91643199493404405063275323707273924529829632098822225624094361937811264494211836161623003705928821889758582195002972954105514196116391290961649758240767357755096013478665044950*z4^2+18562146832816008052224794104458543527235676341171985312030749186954953517507682076561195379797415472679743782631572767726794809999419893442012363728013779293742187081641567510584*z2*z5+2865691207105335424363596726813843666604821815862527893661507807163418134612590371296538724437668423007063731039704245619005145805626862514771110298300146478402027221582249228370*z5^2-25853475175211561521505313570960817271068573799743749245816637759427804257615597964587289171071573280782158355550912308035927172827663499535425864187014641889364774995270114542592*z2*z6-10134245665086530189258246177417039137069605218979045175453658227834438207405782989247111041517304028270186957722694904800499405444108655917599224746982956775740374538981324640032*z5*z6-5706124225199541302155904984117445628566111399602865508287816705321550272813621006814540821751861191190504230746435669188649097227030607646447010310145298489273665908059969830058*z6^2-62397860764502730935642291457067771527961092223828672056068478253479036042491640105054438913606313065869439692769574192922995808925210859719592299815405165669510121008577140635904*z2*z9-55368530030043473962152385086745117222241021622980749042718286094086666871260355253152799054925099419348387058612288995895165326625318265305994927034336764135948594680114520631424*z5*z9-112752418949194197405601188521227437563554124360417874019658344634331647631626978340318366394514289195882102493373071474699412800610276059917974341135353007951784732581246629582976*z6*z9-1830555266127040216357959175877260253059044690470057642330237094310488594904143129791634215430883385094653540521714150138468088357342621589616966286010128574225392960225280000*z9^2+344795799024197967413480863545879976607771052072850364752501843010316029708088983133957505254172696792991961376256100437047510050171753730445187639520223114449154672733003509783850944*z2*z10-83886515101879235959495102701137407764107244021902859538264306900394863024327524259153807041439184640295000407761834969260212653043804164352708686268881725739236769171141864113983852*z5*z10-301551218346766345280211541694155841739495253398340370740814052515289036123864950155320621564025453111352074866324462120556394347141237171823215115969215018112317697400197343327988288*z6*z10+727865663097505432726668164466773490881910900965505877407101786867513673785758409080816949542944269545373534831470327160772404366242018963545223658872491126881711207859909604190989200*z9*z10-925248535445067631842864165420146847286335046958621987662506760004400418894676035018364045012295867239683975161916514576435048186610919993990448989050012053774473332567538336571510415000*z10^2+1501869214592763821330963750004978674999892162700914204818914515747159149917583509738240519209554107809461844260768047903258317277688416536763330267345802453450721261754765714480160*z2-127654444415203491448690028772665734327258388395363914204328115227374987036460154695943888267660471169752690630604610937850838381931218693080023676158153770990770861105615419477572*z5-867825193730570311450632707963122635680994230142991548984165973115003864305970891969035707529242728838486780176326498550584091895038042289393729985084345459362954858538134044835090*z6+1039266088152047900648926516030852279718724689731567542593307122910457036490895401076593521359447124539375604166441935636845970977941348449507937725579968255671568942719618477218888*z9-3773469418751970675400384402971775872952351910120048342333401952831751999118049690887992247232548631103008222993171094542987431753297694513338945421813109379117687339451707842688492975*z10-4384718244699553016924777904101063917205971871080199661699609116648356144190615949474286702131131612734559455749793545939082471224652324212213141018061600098050457054069063521093068, 450*z2*z4*z10+450*z4*z5*z10+225*z4*z6*z10+4*z2*z3-2*z2*z4+z1*z5+z3*z5+z1*z6-z3*z6+z4*z6+450*z4*z10+4*z3-2*z4, -115653662780968234275633150656273457292801962723917271434702672275261041178852767072349675476071636266254473856623956555261322469351282739078265832692412021885050260705569384802403840*z1*z4*z10-12193109687192304887907929939327211000033441747445673353660390411610799358199703370427720541538818268660112168618149198530643762868179471802953202286036138948653733539072270142912704871600*z5*z10^2-19985662753175097420691153210800139776505201640412117705135856631454853140920554742706169832960554012110574118618757291587043316749972349155075878494621862859469631467015487410887809506350*z6*z10^2-25779235544938627913581764221004077335969730583016498013784365336297979607604961794609696826072619257830148432168032067503688302618009002971137308257555389033193349246061089485276328515000*z9*z10^2-43391221223546903024979270069975479413462683027233511983242923621787685949756260218968885304720452911004446417349678901528335678444603491700424048360493011017330980111877292729591088975671875*z10^3-11088657413965074321278124632366306754282859438861798333301947226808051323008792710427593190407695948488321152023267953580539802762199337263990693575895976210105569609913797735659344*z2^2-553366807564441312323603591656810800444028529779508475764127618541918857315085009915548686488381034766767817495808404570628337173929582483628066185131157999450001247395068826805760*z1*z3+8715715712660986168124295214910964492007813023406685961686531729330608245403317049737138485266105862370329335829225809041981440474142310519784190251046454209982288948680632693841730*z4^2+27388396561715955112563327714120535651353599031683438597443773715368951028911524927746669204326591473746837749054613178922593456373984596973476927769696630460334229190378318124122744*z2*z5+9789065407914906962261992906196132210615744362112262505712317968804758455826030717292132902387748557705197726155386633730011754669190206458470553419735868728890752619996519407313610*z5^2-34568012474499980134302081843730873711474963875160510790031286162371241871933754129315931415573993513636563009510559928861497101162245858644942555759543992559699397462137180953080832*z2*z6-14251001622457973913210911986738792788381566409106050509068692040385303841890390412809882988711423084569661205330616910554809083169154158994095282456884663614802660973848050406115872*z5*z6-11275736047286279384013950546711379383024092127480929868834527483430006445765665979225845138349759354093689876405963758600261211199013330421566981783746206350346562481483293275371458*z6^2-76327597411076197429336536393606740674837845000796574669438979381789907566825294333673778569902289671014507706477440530654432052586569828443910186490377497291130884382388241464383744*z2*z9-66759663652031509709105039752437216901719501381964349749745891310441941825938102414140560924642407358978448042893575726557652999970733107072264183564647936916065006016497372807428224*z5*z9-136262554766147661416693332877666667116792955923993056677663760423675451944526586225704302353918401908384080452833374721017234245146547027430117731569082276895644279617053047814187136*z6*z9-2216135625219275590909590075984966214748213692483417091037388860857200100258603204587845870785978845318014288138830264925949714403856443140095866272095991595475737820640788480000*z9^2+359458812719097035798152389052483142565287861010791178853062448388177278867948107663850122867727552007690460708895073087546266587644599933547337197400679584977095849630449221674222730624*z2*z10-73310558138138613670544733924182375059052152020848782690342608022645702800391942112142426756012114976391100511199997869345714166328005724767963706846845032947291700498389763865632364892*z5*z10-282888498247078279717912776722924174796129860034057844681239278942774150708376411676469600160501273328454053507951519738075060403682801289132379407393632317501193270631321574066497601968*z6*z10-522695601196711098858123291325046768548469685770583429088636968774113988863561459973174046069961348370269405078970389511337761163669695657278081347602475287537339646931617432130143762800*z9*z10-383525113031383026422374332278266356736843338481233263305542229911558779752713103787849576728670074136711159069811234103089184215270593041755158405945867073630316739510140566731403843651000*z10^2+1559316690458119403957455877730712958722940285983170367839344054842303049610220550744825160802134997596344135582551542773870102253179664391703412919440239551248543694283230490065916000*z2-100197366479787414761589053462039910023840569326576994360564295832313679381224919520828524536616638872969498146148947933321606075137520672339424386595218658983260251686520969633464052*z5-839561123057200615019736634039217837530805827996029176870566461489196391159426155140892809372527255161583464483489924529494897003187651088327345441025010098795513931660213574633435090*z6-1909240029882628996926278733952266044312278944354774234910406085386271427159843108588474644942961154709613266744432236686864435060326709505220567598216562070622034303672330949163339832*z9+99754173612489091623536781494396451775994607160250541196221683884995066744714591179950575173207993847684866155466382971272625867246151544049669664601070763145292898064376539644149553805*z10+6054315337984613903082382768664401279974537760958109993056607449863756865450562872159956145863868499104657057323731280244075902074322242644903683829277089657174229391455247735692762532, -299734686147667483374602225438804911428257635860807756788203476412711091714836113080177174289522938033150162256600*z2*z3*z10+206799914729720111423192630287134321777313582347227411359912095960750353710392327190339486753064901587656801308150*z4*z5*z10-5666636077338553784364774196068456403431852659228896595421455260868991149656071095783676581266809734331136861200*z1*z6*z10+40683833019222162139601339614373038319984814220570263286487633734287243591765839786150973866982909208580316932100*z3*z6*z10+171589460030848439322321297126732211747183613910445105248207946062465253939667487510353669222579940329071621757100*z4*z6*z10-44666250074753809769746724186066073388335844548300825425465657543847157939308330171415141220165057119307543640000*z1*z9*z10-2003705617850922110379088248219930889419726159553620619736563354610965048907513311296949096833520119558847143493800*z3*z9*z10+2066899109488747036070917094632073374783358183010844737648244161678922407701819079296694906509295119828959800225000*z4*z9*z10+64426630231878841489734383797547968595175642676572574959134219665014995817134958361116780412693039443921620291953125*z1*z10^2-469738918221613625835713086374613647280312190069424097787720606729643305001172234322737364942217536931203420773828125*z3*z10^2+104130756690400455088707304445413705351328929165333234368784089915392964323220700576801790706410314713112989059490000*z4*z10^2-760186206226034667562233288815026351734401621434667392158833370762528830736156300105396822649000898353229670000*z1*z2+649365617964323824461662049076628442160133182006603515630747116556327994834325808989490613599244184435679741784*z2*z3-1105866738093382482318892799922417341827767334956170125726635973219507643040059090104499232414168891697155833192*z2*z4+421450901332047085345374261292171119139383927680775702581642123141225130017474749443226369101383377565893104196*z1*z5+332226278087969562924851454354256885242596496762072701739183638200379734179026906969096825079810018125367472096*z3*z5+154380971914361027512149399325318871507517465317148787970378864526308951954910595517369972066043312892280293650*z4*z5+650292368304946385690509104163659190947589908002384704305134560285840914839178765595026760821860746111074564796*z1*z6-617707310452982779547359898480700017714390125673133772579897309765563678061328535762464395233511475176110515596*z3*z6+850451389604067643367477365632773991134212541041064774877691417766686321550360901927067442463817870657209886396*z4*z6+45317412601513042088475096210725056105729170556146586105639567194676816529673051952052637270299304430449480000*z1*z9-9290897225483578694485779153084510355131520577531164254603712901569830739820184554461990230100966474416195378600*z3*z9+9328264837531609067164890536931585347774446105440671172161997889976289259756213262795778980956918340170145005800*z4*z9+592556061296382915268933338056404416872962133033291895540453947802674368935283810290681530333856162368893339673550*z1*z10-5195317951129874954943475051378536709620381626908276539492926631376353558903275311261932160933900856455812912652350*z3*z10+2350964487818831310824434764289561063283076895341969242222242248777852822883132198274701699758594999075904916688600*z4*z10+1217703292929928713709552346568942277268964990247332917106656837611457518099349816898931249747320631899228723225*z1-11061559056988499174180751234842858653467933687704947585291615293460872109425274018848973085483249755681349359241*z3+5703988014463328474984586787187153605884395847770183238975766430559795947463949007891497054664700738500150745808*z4, -124507531701999295272810808122782430099906419200389407046928714171931742895894127230998454459885732822522758936556891028391375864134156058816314891654510549876250280663890486031296000*z1*z3*z10-5868712673828766773092704677334269354988281262111618802269717496133024986936392419936212218054257056190042162658370792036542800317407273284243540108112461402835403497371700422850263648400*z5*z10^2-9130547861707616345649364515359693351301388129770058126090109303013888689829568445608143755475923606170775767984442339973249827670388603190896084592408584521752411132285595860448752989650*z6*z10^2+28185878869354771796868296829619552376451393744195255849010152209026178310901512919078501499723211014676066405333016017775020982063678421625342059310321813667034250442250145705497590515000*z9*z10^2-22266244087100978995524490023202737747535852786870790638101232738050749006699395987698789805099990909642708211865012873159121594382456608846456664162039909017241685474370984960607788970203125*z10^3-5664499636113236699937541864289369510661464277691528440221377653621925560427676081162861111678682147906311252340113283949263258339946692628023924003068888470428877233918024120734256*z2^2-1106733615128882624647207183313621600888057059559016951528255237083837714630170019831097372976762069533535634991616809141256674347859164967256132370262315998900002494790137653611520*z1*z3+553366807564441312323603591656810800444028529779508475764127618541918857315085009915548686488381034766767817495808404570628337173929582483628066185131157999450001247395068826805760*z1*z4+3430718773322967419348458708140377652304831882097899664464367047917226893223027869212660006523204944460868469898192488642743188596846028617530852976076363098650119083272937734913550*z4^2+11727234009063097758494822324075953181950835289095210592272236295343038136297972559254891752366445259627184966000253523539322559792919223944527562388004319730883326096887578359804296*z2*z5+4241880247845115702789684314826062422663807393079651569515422828348940713517307714396963610691438884513378326351481001527143987913319834354892670015053206712908211257158384002213830*z5^2-14864868277494472941525354755098149314364400582110413192125056731045642308037585850271470464194607642539324796722476007191371248417538053838862891024744542870665759190504755052771328*z2*z6-6166686386286069637017682530297304408886750976032205008488373691672973941712556058146918583493910736969292308173856689441129009226406107559936180099128301131129015158385226103344608*z5*z6-4795934922817910904411341765604889526131656749550881303650872268412102127987403637914305980044504534482624788647265411859694416378378011823588572580069901636535261513704980610502542*z6^2-32833401210394750016495329519169503203167767058616175549820016586462980091690567089600101004651218150241816411822379931315878461860233510404251105290569562512757359320489937503352576*z2*z9-28815026937807660781918174634670735440668166353466987785012648749313384612069914526639321287638999796349507874637220766259494211417195565573552242967682967802386541232188693160505216*z5*z9-58702641925854381161402512636317887169235999239025057042727773498194320337006233577039492289714772490604993743357125664123142013120321649650267523221021664711999236240704538915848064*z6*z9-955075590752665802741043747959988884897144907541756911665646257075265743966165236185754454775066947568384337609745454531390194684178360773744437887620107010196306288495083520000*z9^2+172787786162053200987095361017533561955304746094701183747104289346341201395237018996580804736247186425579929579713159123621299233229812900391006934761306581087441549454604053280106656256*z2*z10-34874096305932132750515378018203652127837374062474211725372768059770681817828376563842690347271979335618145459201508525403925301706331628338612305371746303010060899175253768007604482628*z5*z10-131323621794425888803527497796122596551735633382401043029006210212903526388796448950816397087871176333092875626215851238890504922629468597210495874688173800194934753314207855440272346672*z6*z10+127037659704712214138778429308517556535403149177157565973941070361716252442351547822398999445637399819009086204915056889267082093549084276336397848753904090134030308276271962082749042800*z9*z10-218676446448233780215936223275699998298511181258624573986003118682889602879308585581041603282638090577270990858614350242537985738368221064960302145446992492745392834196038158049967404805000*z10^2+749320499873837284714941784941054625496134476941918495589712118945680806730666200138061306037788508560706142308089962013028704592574767639793680627017050421681866282411445879882219040*z2-45423357994433424029101148368616021374633739565972847726900688504344693106386882354366002035030142708468486997116334467790550641576439836361136970921337822086312597724665045601967788*z5-393102974111618819351022753174889340682846240394072699934736711719973912188972742019650860526037043901567716125289469224195109211155614405701792907755921573903078472291575320652583630*z6-33245276567232444158183815251885481000424428538744523521671770301200505468610664346017269465895792541370448100525499142856214461512474015735308208483953751944355318935385918365003848*z9-246006387535544666226625137934402354888399238864842332682678775708421670075150742770603893253876281035839526876499105588133356325490809892341211597982207867090307471101545775086588724805*z10+1991933812559643653015208498003506476838280921765056442933809374108872200266665592096899104763139044364031058724512701643923815758623726349799683097778810872442816612258002235530595068, -17292712736388791010112612239275337513875891555609639867628988079434964291096406559860896452761907336461494296744012642832135536685299452613377068285348687482812538981095900837680*z2^2*z10-6573865143378179750920971744367827112076283236687273257282546629351773548703702777196186558324464497546425853520418284047183616927816792942296994759805970014829574674706426609403600*z5*z10^2-13578575153291639165700071835936722714825914958586098384616780666290662809619525742529276509966786771416149218423795263083746784164898730737125646223822372002546392779574763977953350*z6*z10^2-33143648718323020366926585235825560167694468828842833777368151513365776737726784919317434066685881557457895292441600549494820191927500948835340984371279118588034619338827651560715000*z9*z10^2-30379318290475523348951452539378322162433873021306378501468648374597096041495718435311265117241377908123625781684995243834199967547204577989626739455558098439811042003637395617934265625*z10^3-78989420447812171305545511100183006034281218172758740650005651479253318657848686594977421945144888441166101198829926485011959403765580994835314205150912593362683177376217250304*z2^2+8780209067424958361710937835150770360890541642001962793031863652326188255536437499607898518683796878197394650661518634460017344870476655384966110946327084808583068203126369310*z4^2+18623051945281873585422013153765942593777040155446191604187971897432721406137000326611603007556301239699825729852360299826101099539643552972941629431781021100186583557834314264*z2*z5+9225539539506448233677963644402790322163169006962736014486142848454087648745810562174743896912376816825610054909193780436321595244268598523909840607158908071191591720024715430*z5^2-24555058937235505861785813636278525090278414428699006010096216636181382314600352977124137517803381677705735726121843323240825052894530459651873851795509690716607099503506711552*z2*z6-9948397551583281737613645628332751917279352980019905702351549982940328495233018375695406110688272731474423214736438441555445166208129205301756298403594909479257975164568115232*z5*z6-10804999930372446848930310757886630251282303716722466565389539287494736741586284653871199168042408642447603525279643437350197021333209794614167210274908696216453809642902743198*z6^2-56847150853534099155311689086566637835157448024664333276251827714761452154319757115590237356456444131061185061028961357326112639588976693542558743820514321139800930260402434304*z2*z9-49017807842460337283240905724209318055501279581530963183551556200696084129920938839629987102270142197665432849378223273271309588870494966449009261949130181487590112476853421184*z5*z9-100363513485260513887107477658676025487910860684299041081376192680577192854479708403956450891863283674093706104327662225773497342376193460029554638192168042779602829857236989056*z6*z9-1633449773482052730429311842745746441342871156309284388535955010626942832948115083756841431018008489727326927345827496899880422972784498708074549972727647193051565998080000*z9^2+289662065225061805803994883813671059204781051792507010355728241678189029721612977198978164669785289981356233418682505466163610984542005406939968848984856028616109602500885808659264*z2*z10-35550220381562020830915984521898539851421177349875780342510983617238663191311720272988313327606831510368902677303582608521041031182610792394711682155920749368456524446532430873012*z5*z10-207231146931616179686341261956930011465105658879075064652439791830725250809044738737357836925280039386341176221373468011878237144665020260442831832572729624689289164362834510507208*z6*z10-522648583152841022773242588106218591037116574501618358808825044885769697198317717615343698972433925757694424905523216193431537973697643255059945300924245518991604927488907214818800*z9*z10-208300468232236896321778445543217386811750362239565347012686248167512069707133343491596064214909293152725264452053999538772626979589597760228100904996709209211930615524126449038591000*z10^2+1284106089726997445401797584455366509453272693677129932445198293195473948369374956610247230382700468743817795235961941707642475888329148310022112812211938080034481371797507466080*z2-38042453469152055267552232121615583651489718623113688898243535202202677425303289320005132182976452030994289100092518402926879113159104522356190225366719004843103484530537502412*z5-644311145776821350069646140508855434648816381522803078464996937277963950113776404678996554203693400635391315848549177345856023670922528487676140408499206350806032608578268838130*z6-1738509075102576641518457363970748864060547633172070464799582016770169905264227410396642570555681379260063557196780261187757339807807329411184293653090515164396211664644014691192*z9+879580898935280419865582688546157088246645490876882321292408239315652997466514964766355464404538695867658969264393749406750227019237595945002631631178973730179175431332509882907575*z10+7259525427702581631845237288365470108440923096193412106380862425170523778648508931717149789111394335090228977338603901635409280933543957798699836044782267896708431807998191735572, 8392571212134689534488862312286537519991213804102617190069697339555910568015411166244960880106642264928204543184800*z1*z2*z10+8894543670513477338135299452849200795044933473786765435520936289172514201450811469923846572506308107688598081635925*z4*z5*z10+92394433243591168190838435831968457612552165750890739417704272384442867949220555909486816130898282220960590414000*z1*z6*z10+1320484625133039409915570244808248575517099517771606100384493076250364343156893686733642429574766952919430374052800*z3*z6*z10+5525396178460006651474871934533316750745017614302905708044662960052513208484971279603420326927085962463375645456750*z4*z6*z10-39056581466104192169423663688840261383197712098564890130380670912003409952252319262604664141199906390420254124640000*z1*z9*z10+92885639265009924187311988704146668340914106105575194599034801121415195725470602669275724698240639860604781271813600*z3*z9*z10-54357543388106402613531640405599573323258527571018627720932363759278487667226456560532835807218393265811657869260000*z4*z9*z10-236740731862839659031033008816690660235130773176292426812352349921637699631184405236877482550424135007371566243828125*z1*z10^2-7107803601129060251768504465670775911780703687742809295960726256685594952837212123857398984213258136359408664374531250*z3*z10^2+11417047914852867823216115584588117233910644936412662518309478914983443222232932174245563975089806384767361575831644375*z4*z10^2+53426008008534933893814009052683681598521941624710192122398310615508321565125579141881913716023069991801809839800*z1*z2+97855072334559303190889619969069108663526759836908888166147611479597414364905329382407283230713945191741329449228*z2*z3-117010032516750730173341523000192865111881480002838568958877428694330124063828199188700239643256626607252827127364*z2*z4+22440938120976038002445132221734942763859316871458309381467929328901407781350988274034184057774692018656159989332*z1*z5+23903821040733440206646890303195821805249095742436114739358213571841784547425791189011280627914059482444994912382*z3*z5-6656440126358212574880076665483709597105380201693412668858221550161868048307827324546672057441744141122494292925*z4*z5+19617597598212000108429197937354334426589840000211327753817599141314177066302318285237581030723032822773039773182*z1*z6-14451849021314849300451092518906843008453432082878135871498468883464013900798869957936420459556672660698191893582*z3*z6+26594450985151800858838543499949645434175832686034410105680238313008039131663921639078390677779461902596318155582*z4*z6-181246718028313337592552867553674925144435833099032774764297187412734879384011582111076875215995294274237625209600*z1*z9+424300403835159983212431382185234794824525104450820212610633183027708809051272771103965998057959399185470606879200*z3*z9-245412176328065304993840794774777085456219982619081609716666936986876543794536686630800302374530443973056179045600*z4*z9-13307547347743585409228155114537511333425775234833529574776882804841785825216369168123499498347888521056615598687050*z1*z10-47178837502144348894825073044168416101701357066650342360195072892436447321163270875346459335090358357776687298644100*z3*z10+99379594845442739845163072830706234799524642504868822019867763772572535104002461155215829016626793167648724057598050*z4*z10-58494924791863244365578989004181202952632746822208569522334885714215832645829483892388523641095227564149139428925*z1+10222006118510022378624529599328310189749322692580264485517811678251027223353832657139643539504442772521436392378*z3+142662867126816398084120255743664155159000010469409831678631273002008472427913819971228349244648661589788887512911*z4, -108611847852083117096868850491981832329208527857568187822268597132653912690105003472562827303406785141374795800884322943182395475146726263574838438201353369166062487113502699325806485792235227149657983418368000000*z9^3-4097874627059176776220270798210613067330379176746265021250360640377457682781802077681311404881008492583213088146070366574737649366045978792672022135708826258325644426982274436515472560940483809551225720212243187060748004659200*z5*z10^2-7834546180784368106609274229819052907910554939542837634085769733498662790550982673955029664181550536302539377648368168595766145912875206940124599581810397018151563788504874004293059166897521730784878813379951609391068263228150*z6*z10^2+211359720174956123101150699988760509551691446280497070611830456470191832735151798666435262575008919071445178388425918322539041880547381251206405110114268382722906517022274221008425002665103565414376747379556126339153251626125000*z9*z10^2-8457196120976253330692915097388297758422343303618233187994015138276937703074272597343747213184143973903081369053302772574171954527542989617551208921330305054770243315168176740178752078676184581553264350596775649198789432715659375*z10^3-2057436553837970435077634256337517637992779830321021994952308813934698572069662352880097154051067584213300768707574990530114688379554725470290283682807805872996491985257075733435171350161344666837163735812124731424743088*z2^2+8300720197807070861208704896654169101667402292966832284636291152202341368082542274122073053036503238300282505934411530216111702545784249887124752704995484979934499743161761098904629754015901485775174465801962758039919274*z4^2+12533086729455041882203720786941738749952315261222413060515880933070266207856659756428740441813190207313315432645612687834629888662625814541293061189504905482083531013009842370771596050893058962115052422690123377772021176*z2*z5+8575792281847001242360527415619218582582590030411308594816604437037578307065258489102551468291466831646361503455164440971554612842862465152620003489460103901074291369683704169288316728074939705621515196431099345479845202*z5^2-16770167230395953080828845734788105432121723886261329894706492346387248038590826423079923626832105687677994679567708855086948593496427436875546696945077739289242102876738421954198520833500024750862482183630451495604698112*z2*z6-6629120535146447758604061824720516772282764150632268711476065128046775411148134938498595859434088159824688223686517250869642441294231266001489576378805091411334038964808432325505834396877865262001391359423535313772477728*z5*z6-9569943774271444675734540937243325738522059104669824666479023717896826669798726132608169544792264756460571228851553477805462218741725571719008029829846501616941048413332987191919545903385238602842944766083190322227376938*z6^2-258649077464410893416308635611378786533707009886913829744019748698615035925952154326378272915946433464928209808479285745397780248545047782667236325815063128282271597398557332466614210795264839436940744828944027389818871552*z2*z9-64447358580098578100186561830701397817614824926945264948980455220326639626086940049640222637372242290714973148387962776268429016384454195743929301964518432314854590830881151414518324454560136437969680751565897732424523648*z5*z9+52284653737080529070665287297061262273429608738649728448658884396400714082872516894067083345275639001309886610159346421463148962931661203736378111258141398977174174337310805258364304511874727556889682862705262613153988736*z6*z9-3846329366953900422011213604719331028576239428737042545461246503933769027291840469975835150093446090968321823153266332071810359130537671081654556497432242841197233789100133448781636734349703787583006590561921515520000*z9^2+178186882856743582007636707536430010770135515488041779760278754212838384969412666200151819751666843005781317958597165059864545200832884913746758269307113345049362257712808359612546431392630814721170595692863290634675850384672*z2*z10-19856207996343429329895107708434025853150887859352620155036529354100417383125847442921260046078018784182733762148599819930639033240894060049910146204462094202134405230250645389295068264349289624470531919952474345662218287228*z5*z10-123802309373060841691976155961745139560779778945027499719542962287349291970378239388690281794794874342253876929217882048012481706167063338076280682711562734720688130246402406415156126225358650271951759225871142659546821866120*z6*z10+1653002087301149284743595269859799909383734959955441408242199908267403735830466626510421993480629957836568803762890804076070201320122099964902565566032306075599159421054042371191955923392399657505318259666507109197746285862800*z9*z10+70151120772979483985254704927607767496733235574715301991191435820475803319606014376600114699298278655770817203294968322480816059591925889123375640379258691541664577336209330214366669818394485008869274572850669766979161576095050*z10^2+774686906990760069180548401967557984430788715561757557743591581450853060741136516176986375522400239286007617670049368579740759118968386672629322938249433342371010659532516830807798386946665848853788834806553353837247080736*z2-14111922575506950490347146791720782969834557622980083999476685973187175714356501448647186268464206426791540499135757325523841538444289471043161132440171858110849150192568047805684932010347628700695569480730518249406062916*z5-383248316135356131033522149372491490938581510197101984381425979273331224763180312667015468038577459333038353088605006451827733180281860798733350344673486175591941551909296283270601119501547927707632600181617472319946614194*z6+3082376646120733584941628474154156019589018663737118505567833135327874073439579414473994925631866837305832364535229595746089140796107728458741839592324063170365239738006817702637618864179293042391457163006362966847469168200*z9+1983255128357648626855640786003370755910154856609766062933449337976626357500079523912466970226973472209344258272505409276269262265977687436092972472500605651546907766594946066673111041779993486098683214672845181244861263185701*z10+8500019000031912098541438630918496039854129329879239011007613096967663753231755588564747413255986889704667422700095527958168769932496488152737279970725737448690047045098251438625250263786498732175487499939237115236038750742, 15936964057855909794919783439716151052788021657649844102006875414007263090674448285567802170865373801282913143879282051634096110609171975528488306131777350384160035924977982212005888000*z6*z9^2-3057357285085927770605619144898166074473378156579358395629951376503169540728275259725055764652783804111977279558776155191486461791624367354258510655601387201731891770271697566409649015059494800*z5*z10^2-5843549365697688331629894976606251876552773294817014190742764273080020403643200828238851129864850551704786117519886448464547169878551987433022053892969333919783823730699245519795848551492174050*z6*z10^2+158130634157864204492885508041890762769207305584171928781845002318088030523232335626858683405268247993514685668795533642812049818048833311925658621484255402559505818230208191991143675511184680000*z9*z10^2-6270359903193856653679697736835196119580121633929288902534724321913627793111013303460970454661092371506462920347362898691706611440357017289059742933724843218232838358344917646380651699959762640625*z10^3-1538972682677618153374444790558432525361412895211312300001944284322689936163883906042634243280784382613460762294891265739765273669091612441812726452789101860491919497626677983479524141072*z2^2+6206222337965012993528703188635988052112079982071430736751963710795959514763781229313833360178175438723176380176577936083067535604378013670279118319390951555904718357795204637462876780550*z4^2+9356195071919619654868296319626253774286833293107167857857963789555251470646957410611298639612816207599225156854785401526496023891210596888525366560746539694352044839843708173630462355432*z2*z5+6411459054164812563282617584195071232612214134572811794937531749753607708222775484283388758641354970987406943829877037876580341196488072611171091198081587955949885110568719405446649671070*z5^2-12522910003111654807040252062789555638642250151932995044514225664105854415646375680808589342216607217640351695182155687233791405973674982001130384690592313542427799218144058176092773405696*z2*z6-4949725244203548647151272812652710335910285293950932782139275888364222302822759313741618181764224748168726327193786884735787554299607051117110906500174551625917414397562928301683497097056*z5*z6-7153423515077086988867000731827715060048856470844834086356082052756218360843560560349828393542826424438990902546211712633107256869630692383921282025084362169614137992716705520805991174534*z6^2-195912490837723727669455592527041011525088877309536109131415770430882639748263255725974756201019550799966434983028963847969006713250791944605941047337299083554651280953303301950506181810432*z2*z9-48206486856272596891591770640426715326704999904725335961783648897927721755290085684458103940170214064665842404730397944582147668813659437786223817545896385089949404561885696687609135421952*z5*z9+40057780242555194485635334468559280486787573936195719757881239205643631879097254738883784784983369576366425993510523636415308753123968152309162268834834441352630400479591291742374272975552*z6*z9-1531748658920302953372907276553254905112331672313649282188705932625732217900382604244697660091482069182600633710534506266514631437069579604283329757119769076359198180200705990131712000*z9^2+132923504013947238090381825625658138163904463634045059946836811580728621279693169240075049450649623487909534874991054611617886593474233557370908039866628083469957816995219590651413079266496992*z2*z10-14815897943343414660217710628141154780718889879418644773430122756768501041461806656907602053855822243105418806481939906308277892869727376722055117008003411421527279707371213109562792722248596*z5*z10-92349022900130526768485170898037391587354604780069688129500582878138667062505925627924207287274381994467286595346822539960818498238988863308568263599237849212102423237090490250544142322110104*z6*z10+1236853327467960780692202986645558984445033546147470383676130324744603185291066403565690777396615312779360493259458534021175389945417609672772659559167127223249812261247379918448855687123433600*z9*z10+53125470545255623044286749916477899652272565734786927872425033372512392642296604052882850032647715924712352963578875146973816006347513005092769944483818332457992867295249270793697195389250478250*z10^2+577864223671451695393349646426605771279714042446215445872339756755983626785205728545840274746641355601788513679327009217088618156397591927071567684111931399262957017884370389398560864631520*z2-10536727790234370650635937786411647331257931101335714389047020480402098506240745897289624028935112938704348156934530191397462264916323451586112522406367833723727497490513116158224072878556*z5-285872707763628283273591633797136363559392397017480533472114618075350355531881653159922329353943127033432869536603519552198945742824521216352607231920819423167749238123756415600775343029590*z6+2306098871634974770006728347760274943660282883283206563228182510244317058788138575306206232057665842734864868069245907681245277169865470932129455628779505004004229515721626464022848859302464*z9+1485613842317565831165169901385583046550078276442547346978591799472620930236739030333173717980770579238057791637404323905871661127290556444596532269381190832738541600740425639550103095262446915*z10+6358981719599608475232289968556310100988013766361107530312536723282062092949108328017164139892962199288217672958036402599359615717801001246691072309538798558103628032714520527752410896744206, 31873928115711819589839566879432302105576043315299688204013750828014526181348896571135604341730747602565826287758564103268192221218343951056976612263554700768320071849955964424011776000*z5*z9^2-31164476051015089156237862817963847928797836621516469406298188812403511585836606832445744695408587283038445491998279421766738805799778308335787914925878865669845694200299821150713399737553666800*z5*z10^2-59549030011576713720013399540530708153068407114861176225411628476102283445740299572435419311026813545490971088754424547491328945577183659926625159673761780529534186813290405008123758035169248550*z6*z10^2+1596851415530020695374250635558678351432143947139217940479998914941763855332710776196131980132229892661515255256584582869213554120176842018319708419613454138349676576464672645308322293550030255000*z9*z10^2-64695882348595686308314056307523284837498760057353701886076166843431150816367288733020382005867054334028600993708168349523426457094532070590259168831572165843934945361684509488684459561859714671875*z10^3-16370100684716765662511280469371332391010759613403174862711789088236814577841645029278133540510160192883904349227122618006569560305932862192775258981633501852533441887045839531185976190512*z2^2+62968801443499697948825149154934432513750021898663494102830281600370657154486513955029774535587121559011252492104299514590997517090122556662900841065767545128671083941607331014717753553650*z4^2+94953156358611223171052398923528860740255550142488459561521092522592694616594439104017444751338989778856891534404808228966332625891103763924427944070344297597351597455064074358544553911992*z2*z5+65060708902030674030825440792864680104638940306757551491972990230694083341774291506801836932875384366446864240707059050987607093586474298644282570787383549285351260694177923484170670752570*z5^2-127058704198262560404116120563604754865550466516791278275480502642025495710494640387559407930520837438355986364003872354195554969891307460855678889577636988670309431432159136384531507772416*z2*z6-50229471103431388560174221841112978767818474294989352059567907908353662152974321193218440716424490634005491803023725511465257454071350637177503597764732820685347697613159123560690033626656*z5*z6-72608549325300085707220746787050661540009324567139137163522208504023093275998957461261699555233468887719413994277390787074693475634106847672773370236398481006586614580961606222688190652274*z6^2-1919029239947759858672753408538383172709793895074383770938289199994074330680012571410191175173918080612684516799862334783017180089144243927268231276734601087545846146434430797859492319973632*z2*z9-488898428833718185476337086143802265977794121735164921634025351738055150030921395725858316764198982036723375417785626975551361225310403457563073276699177428182556524376666534383260204457472*z5*z9+382907486015552396856371067960068342599912968661373297336766320986918411696683303572874584497784992036327985239937396411020303771140223203988366419001609909891750432586403078652756158465152*z6*z9+10305648247443861393754047132407598849286054796242595171197139668449093238264245314965084098859459762299955894932183489689861784016493779163970943858290618437472906996161732338728960000*z9^2+1354003864728684222431979246262535641014902361774390478840010419750377070455203747317748065417319506391692074512179626171786155194214460311167163137388550686230344559880785547575533929729023392*z2*z10-151092364430083435802311821156557074046612573708351081098901458675669064819364177928037770817812764465995331783298021278517663748021719866996144988032364775761427325045565423367716513503191996*z5*z10-940828609636604818165511256015403219575126203331503920229325822156303114862941234878649152205613399459516052520738320173085700498521613651326363544648269879296983078822739899655936359577256904*z6*z10+12478590052351288674260708243136092214105051020436333822979486934729528058584040803688930852867643553536132500506096484915560562615960527327939102171843875553429326670859228300850438113664695600*z9*z10+524968508284625294921949655694189581793557142450152090947566778711287525574046301356222776863148741409905454445676116540585077135349047814970043544607649028564243413877916142977221994397278900750*z10^2+5885508699648215785297220520247692177536105498505666623716523133065887391094270821437411272859666334326151983481059483189860236114868882672808487750201793689263527648027087333735041962734240*z2-107980779463361140740589522881311715722034619791098806211340564324981526092813034629482134709306060864330794977618156936213455318070050326043669557293058154970232910407455772588386889545556*z5-2912163394838478146296655495408265918298569280909789579869715507519246082362760722653299320514679975989173999411817045079331929235427105812185267546798280511196828972609455871067531385383810*z6+23241906157722587311867497951516427620224540811505955560920553480233207295184243215680310464247309422119542356727482296589995630298719970457715689322678572961652770882400427632328333787850264*z9+15013084330863946622620741129521727415733481863908757857874423341924614529352879151043973733942810947833323975505090013219550845069053191870398978176063907751398668445470729571264261265181463865*z10+64433264122685270419482007758319952749940176752575866798114185891902061343489714326323357532369246375762097972162324006900666841854075908682792190361933903994081167464627969614328397607577146, -13727071192796995149291548386326106088946093477087310314001020704260344253370935673368564271596443505257905584168697607799315125892064182272000000*z4*z9^2+110205073567184789510022612571704968708084924004444234445145331148051718455073133474739622193621706656194248704165200281327622594048124348097100914958148225*z4*z5*z10-9363610952507001301805156525557181228642193861882813849058105133737783995162780863122953706603742464883067255649399534599430242893879310251237684628477600*z1*z6*z10-12669776876099128556094546928023473509929185154656349972412692933919834863726827773289727418135176337071816238139968695929156264365096926631467491079125100*z3*z6*z10+83759671462234637011991426019411648154770003784671607128513445020658071586293528314041535301738978141062492525480038471943962571454983408866563988008016650*z4*z6*z10+348618750387228396568547102526635550178765386051010416193820336737863071652263347726271565644498841301726540311702267751169849697484484717320558962960240000*z1*z9*z10-1418647880288566509868711488413957747684911671397406964818746959553723251715588291407546354148804062393628092894375766256204283344573290091760073252128874800*z3*z9*z10+1037544143398890885070178009349686159044311503637204000900532483225490405139735889979165187902406269290579884066424036098040095238816612851853458798376710000*z4*z9*z10+32900669879861078266270651232478267032405333728590351602836400947787315348264663869308632336390254962682736265746018692170856815556534071257484246838844765625*z1*z10^2-33113382437698120133460296058976991288135659742207416984620735821999339157604774864020065800057783301146884334285981625835070367809906966142549002413759375000*z3*z10^2-85441930233541944280388336874291542109872633182858302577518221117900486798431684737752848254307553362881424000142679519755807394715650672781789300919044423125*z4*z10^2-286243887899530640824715718509687387497192272404201519917363430342086761657097016697440842363049751285192446396734342227192257992783733766806896046023800*z1*z2+1032491890801335709285173948191257902374037338587458766769352403030460095642173572712438424107014576479231004896655123738956822322807774636715116556243268*z2*z3-707407723292118979799674778827618061640256267009311009520115705005639408582504061149385092980348532644639636161580148288359678966991580435387224113495884*z2*z4+210606169790562145618961302261200488068982439331121709290008657212414441799067721997689768740207509781035207206268656574102169702034533050399407826308142*z1*z5+182411225332808369511397595962020179155949942954705071354204552295121532456559848457465101909208684693930602190145381111658864525978974199074529330376392*z3*z5+93706990570645890723950674882915447669717146449330891562380180940434677883320602044653063505430951925211238347513787462563634762589541911119073843485675*z4*z5+281550745978469477324435652648315381555028163593105461395737017604656076360739298431881961276846643882470861369407669819329040374351640860238805541942442*z1*z6-430181235930100747291171107658201288141267881966738647865319055228401013734951171089304731768073803125559611157959561790041791622196316853021845648232842*z3*z6+411429687547446837684097273407445500956278053583080553430596504014053902189294714382586935787454690344524013153714933709460212453553242044354785978761642*z4*z6+1307894671650646738536622085778911083431190559029898462887935467984587625262505353159521173788362431833724923414282582094227708469122185056411796360160000*z1*z9-6104133265054965359585262169012438068122168294846087407488133380737807051783998312149330967579364751940667237762261193328012356682830654983407347299362800*z3*z9+4651145821085500368122318397349864821257650178629528990018927006393187102505019675450014269563043319413290489542910392167243337535788752310930408110746800*z4*z9+351693514641328253470716164298839153755455689663189198433558644450288158832381261523682741780442858220292277932043600469920119382615267058126234534488656650*z1*z10-597868737620433596389711837264584401251568619648895930693277538292558231921096851488507167257101389366023126905208098192894118037574293097231798687461779900*z3*z10-327602762568430409152724611927135721728008758918836483515540077573871799135983865285886570953430223926194435480993014673297964394750144837300703004381162850*z4*z10+783851102834436288936384336769050203527540310624510265963731727936560253514350020026680313284597710838919121046003033395294300874574600630050996668412225*z1-778147786182530586969423504215776871564479181449091808227380756574896496508958510045714006239005681517635992131569889413129225192038765199169404438920832*z3-909550397123935640282010374630472108339388239665308073440350451394986635531517145793900570766408282275770875154579616879443825011709098095254756768171009*z4, -20336401767106659480431923535297934946586805151240459724445956598904213708697682479064539661624360748530230495064737196739726112432687677440000*z3*z9^2+163367201195940760039530197235122345014364585563724879550790697158832761986112621330709229379173766155918316697840365375350824359755100527272711976291675*z4*z5*z10-13879056865365535392873455983195408333290114670856739646183791154680819917830232679960047412999971625614869548621516719568113998382779255999694206015200*z1*z6*z10-18780280072011852962745373914310943088065057066752146485386636031072057443136748709315996122419098055601092282118756056395989990243518689901211314931300*z3*z6*z10+124162876604531577348237738323841638068621029459080765908440029916954819206428331450317832082437110136126624812549412565218962444073114289056154086983950*z4*z6*z10+516786824366608190734787775814008628679969180237454654969366562974325577972826216245436928047817460563303560068811143623620464359184336892113635730640000*z1*z9*z10-2103077998524322443612480454259800976639024331583092617560327643758668177548734077448901866541829205888615638211854073135330316811084830077467657637366800*z3*z9*z10+1538130564215097592347781927536157656177009310297822271859636095587381494772640533125030480070225130350124438108460963180551957928642230491124454949410000*z4*z9*z10+48777325449187619896215735476112489030193310110554415666198163482360183071388448150902767468826293735554416120929333313526596073820764831248468425488671875*z1*z10^2-49087991907417408323776169838661196916992326218042576386769231108966002415826897498154453821921866201029317629733783984953528607621782293181728463028125000*z3*z10^2-126663812272994679428677466080691313617783700960765326792268056282778876693180519285206861586697216723737124603220759050961682878997184298490110507822184375*z4*z10^2-424328388778574271686632373463153507948793729121061633054260067189518873555476802532119520324254779214748425221620720023573211318404251725708121305000*z1*z2+1530556047578502541392635019209270416298631893188478400177732260260814213181163237526537558205829368201435829131968620346755211934933048759863753745964*z2*z3-1048651608105064696646146052637633795979697824873231866880089564338689054377751580281897839397529054044791671024620525494370487506805608269957940668932*z2*z4+312199225974906574786114322188919729862045332201990048751087857525319358386464605981731867012223534240842115954874787835897436855334911466904117586266*z1*z5+270402999292248317331087792851061365512022072351073101417304327617695526695389251257388100955825051588363507033076795305489825025372385174829468763416*z3*z5+138914492858442692593107116647290035101219054490579097040624410979619174257216571619939035731409085551271207640917609595203903474579269841482098857225*z4*z5+417378981694885135903960477190353587535920731120041847579927443996109135324674695433606001310386348660154667098419776948682839048289839387961457942766*z1*z6-637689903781737774088179941629099973745407084262938987805660804498901119794703986500193743135665822796038574073729199435985261969288706312422995431566*z3*z6+609886924250031754421503566833802420930721272792581011650074328934684598727882047438201336884383729950881089724354453035741356178653637452168274755566*z4*z6+1938818010364103446806682423267818610263637435606409033453650666774590388433468713609146544662725502442593859091899989747615593859354465275621601542400*z1*z9-9049093678378881429065045442318617060636176084302962487556535790478146101616217826365845466164595532358650780237464980318506787554330434555834879890000*z3*z9+6895168443833728355967477857978053120466140608924939041791394771426312443750732861349800555378669179793696080492302850001775952892980742909224891296400*z4*z9+521391630199376219236557930819934852894043511208751569330970916870042477818075441687649041822333310992594093995936392808318477894386936579742265061569550*z1*z10-886288746289033166053065429478963107338951447616164391924352987306004055582834696339670236459062885503828582155627689966889024605012408392242404698502100*z3*z10-485675091519565587787708374215262183505096715127869287557127057694650078375070650859154408328128955526377944282215641076293893260273562644507017382241750*z4*z10+1162049190625366410688846914238876071180379470208904989915042787657819151977940852847847857884375141050036277742956353729671316106351128331698856397275*z1-1153563882498912113043157467869883290190049440918301724434332033961618737058073836792977281679056483905247629628229888605491153407045023528267751273536*z3-1348366369050641582105607940260762964267346410629731642300784972925163574452870022700477124586855054968247226015777942031755054665030188650209681615707*z4, -127495712462847278359358267517729208422304173261198752816055003312058104725395586284542417366922990410263305151034256413072768884873375804227906449054218803073280287399823857696047104000*z2*z9^2-27097285737476634142558130980625495061115047421452157118068258136192100471013130456591141726585885014623949012734903240790098211940693293701683318201831172387924135376093518842922961304764557600*z5*z10^2-51614218489451288423172370949621882036637372657673849300218068024388599582100201294170538659846528739474765403554735757389179579426815413810595851362727905068502463857308321080732261203974897350*z6*z10^2+1356538052193950860026559014955749435966026648199429413530199776927309592269770749585993361198970393583190848166084336343540551773677810443234748154737235808153659015594956555160974207735085085000*z9*z10^2-56929900767385543713126674887305675746275196802676615385094948462223931454649925781691906577176648567275022995371111539117096964482036942145956196122314557502916146461114374695685626248399984109375*z10^3-17085848746235490634256102044528697231532803102512044987279048006281596966980197263906628747017770608119100539879850625640950787550017683209649627657556864441271575808220155457553424322864*z2^2+54395005491784968455821295867123728665896271741588826626741609023451809799736597990797150875205911956719609956274607046725787856382571065019009433677602145913412232702934449708271737702250*z4^2+81272808937559333838511474212486216821061648530047622371785821952972286061998516684546831169746044229793021004544729339940704182810118247779822977494525198873530454172500238542480804771704*z2*z5+56213673878023147787427526881357616434308416428304168738636454052408646674161702826230783394381828791133779963745053502786411357723230976629249233687210215041365296024936162840407108836370*z5^2-108839606571196028643012544204345927476510944392306340553386857979266112788298868389134985195200396771060544722245300734880154533440641521451215838716159779111588733937838685677445415181312*z2*z6-43033483795548682690798685259061062548792297305876140929162249464585925738792749658742510639563562385432980092032043068272759372527826087251289800796928212574259458488169018938729299368992*z5*z6-62732068187028808017533796117482297803795980415108714563275590852344257556822317510643318975095732309959262282806580559684237549283618395936502941113752319617318188918020399586784957209578*z6^2-1539304632530632607542209618680299379476332008313174456761938968852978091697666671964139507651782368593385095736427562082162306152087760210456569458575449740591042812927531267248051593620224*z2*z9-422732784454672073235081446550153602632457321457684974829061077578458563149580930983043010206183503410870718227710183225272656335313599769644376902527102123189303463258556833032651188911744*z5*z9+296171060219721794549452241696571116156310651200332485510597504669430892627242869806949446292984539539918828784962817703166367120682696271886876280400304067163655388298172075475839727073664*z6*z9-13523976108047558463843016193939194328299205150710713636374839987795654700562785520431848646007823881926399276079187761973753586338798650906578068870077914435317379113253603231809536000*z9^2+1172622246547062376172462548605466310752567160197724775158476182230307951647752343762996429856051596913587847160346451991824589491012967853740689469107858206502347101293434839261082050877510944*z2*z10-131727008228061559818572341114508294727606514136995460642805371901115860361257249120382948452641422698781374145859016962634534523255335365823202363407541790789966010047513458189376124530570972*z5*z10-814978520218742989333285370221031491214864463035371366531380762209862918002044326481532649241050259929340620159787454569140523347365013916744030695473397635446715396796777334617874594885382728*z6*z10+10564904601579657743248427967116772568277667957619280385449828815812301416263426366760344675998760475086416197269020480559479704042871613543579465356601912979104135126221118344937334613598893200*z9*z10+439025902594657850760470404554982177267278780781250016029426782773659682013105846891333352648002032906795300354019107110136114391267856599841007772258722939067675193606621989854455369517645575250*z10^2+5091928742273350398408597581096462030773292200422258374544608534977467970941692443275853090888148451391997106183691445699399151767946376713292876262341893914661415534820100705523222102585120*z2-96560286702195059678303879926932423604639964055020740813824131276982002553610066113681527538103306177000217063949624455077278240731060756869688602088407121694505635510943327807582671405892*z5-2521296731634009983012174606316887110667824365645499159303546603998772215509140537844554243174596246394406926620674361034128531920706800098873801116549685961255885470612350127711842181637410*z6+19568727336505434132232934679968453857391478770403738603048222328429113045864837189861379415554997333419164848406714971765957846762522593883533327338920985306965448129686918337769032515330248*z9+12901182124194039731141195652548452669880761000912747709864326417210576640908488401373653703141039002079898622005674112980626512344659434017658453689541683992530116141717272186435818824110151205*z10+55551009713193334516743293010083970325112094315271858998679997221856856178670525996258568070350483211038736943911740203936786896114610142461834371835552242329521938824071650027387275085511102, -915138079519799676619436559088407072596406231805820687600068046950689616891395711557904284773096233683860372277913173853287675059470945484800000*z1*z9^2+7348368768871431031052473545655269694216898798565646818851244617024059787093125641689132088913412059772042544634671701779176764822947131489147216212648175*z4*z5*z10-624434652873892306576084397622693156275733076327928363707949172815141665117099300268437020342038929542428946807258798581253768731964724854116769394600800*z1*z6*z10-844876386609100116823110843461560044331806227181152890126434922682271345293504730652491635665288220374882951911334302859713012519298760815155724902105300*z3*z6*z10+5585110017505966093969206987579370827508991098773285212505205679065422507498743248548094817004690427912153753600648155099451080866467353483208427211892950*z4*z6*z10+23245809616003151565803945803618245598442849099474788010449392468629426945582747444442912219169933752036917959763096823373162642061315671475305698898320000*z1*z9*z10-94589900904501800038203805568782665031374746712673773025367502889439900692532481119440950217964686381763890056367928136361755413295514328590843307676392400*z3*z9*z10+69178161346264950979086126118757564277801694706121401283689276590352896123267469250458726593785899783239271369133137711497980434626484254996382737947930000*z4*z9*z10+2193500383949227120268415744895297549846473299640998400494634764032751254182214540303281135495408666101362649628165197822914808214226383455208471045213984375*z1*z10^2-2207910588875586440166239086720212148560267022591647851733172369330767715912092121079117447358773310557750695485312559749027719853512658501523061298815625000*z3*z10^2-5696928897217948583722240962496545346694714884049242752293232983616171594152993233013513486038034099931648294330352743349812606304405295131559347661869606875*z4*z10^2-19086339581526121318296529003535546307419973632258556432496377097072238005811962360259738061372455087634815287674440841989991064660657670624188667483400*z1*z2+68845672522836482792840130560826366914032133476863698775071179718097989364886835213352039450010382627120954336453820139319614919606033793284772380458364*z2*z3-47169471119717730633737015591475736907443626851454437157480575398570509166530438997787671036205035591802584407206106786648480030630773048289966611090932*z2*z4+14043106703815644813541900532034789262582872722794461480449920557699179780816000835032786512928608316426851261073385322987724401543016126437090264814066*z1*z5+12163105502339939230598821804032792275937545946860661222630586605703278293817772160857073750286877208139737334082241885441062772182401646534039513925816*z3*z5+6248102535991396859110578768609231391695846134901392274546511815848616307759680357749424356073720993240870706432655929914226393162933146655551790359525*z4*z5+18772997866106309203265548652875343221385328045045134868986832381552467936273730151872224938604372491380005651564530582366336822112918357189406789062966*z1*z6-28684468028926945599914153491316476187034371506602860918941387537385193203122798348407516864794119139100343863481648501253808726603305891874502286062166*z3*z6+27434433912905277638455775297767882887875725373610640622978150071759320291083355010839178601599102953575439430654798638767725063878156431799895563072566*z4*z6+87209401901990398468785181194041769927977893735523492524929178148717872092751134087223416471383474493725158699885683204304304287938244763131685177376000*z1*z9-407000006706973830339425935131022832245616392506861201310373005114184844315197289635158259221351525861747851022770397071868676112061763890791644672048400*z3*z9+310116567455013609426528021763319298913355021055814500650411748093230320584442583518384525699366424951245304653186688955690907958073565215082024884920400*z4*z9+23448382903155562823775224157841780084752039704171095709881637178618805881742559274602817966136575831906357823075697170878413813072036759596637870828116950*z1*z10-39864602323745261375738882533293462816036904792071687394585378762178227248122435181757993767265678707839065177876124038865332707506647746839449992711917700*z3*z10-21842366574945547409310168326706997227249070650644312448153800773989672241221559700668351978430793453163772625851978065745355041764962879186337387647335550*z4*z10+52262772101845628065792069828305823548170419035137630335241002119066120200990702093764619972696511104003957602403424787525914891280698405707797846808175*z1-51883788288563707075121188987346211875330616295978208620961265466670250235607763633919829126981148653173494127383441212109760576963819815070761756367936*z3-60645417093149845281169204815683496234817084133129654602423436685512418232419453606548640010846466081708218208054909206261873543874032033977184593901807*z4, 4323178184097197752528153059818834378468972888902409966907247019858741072774101639965224113190476834115373574186003160708033884171324863153344267071337171870703134745273975209420*z6^2*z9-1261049500223091126959969103853031498184209954447825198156227277475347280873418790478351687877436633489422134280969092585949514224454955218471683147929152863179689477023348239482068800*z5*z10^2-2658206856569276678205078760861798290483886133753582141916291717050656950663610918062465735980319113332210643310922491003904540540881853534180180027373902688054415676957306079290996050*z6*z10^2+61266391965055163236070598383018774372087018694818111257170833854047519232386985824653155998763757118327800209831433275711304260829698444716309462852750035186307496550739295795386517500*z9*z10^2-6610485085340396566837558284771965199929390456859611251032997726378002052586982889728877240906658065215132401738324768179133557904466364337144615669696917847930146556608462421229647296875*z10^3-1030573075054118898522236665405997817535669550417086774227252809428603348229541222654890838399654458285857807855961858034090164798420029134870986762928746223042347344052917830912*z2^2+1592781026123482970984608491068829290939871222449228611765741064616634386658688663559309813500466934040262803174732083965597582149920029880858342270057690570266130232164934310690*z4^2+2797676344049507924150876833203302224885457572018668817740977494316334463665048241982817908587190058098100850823008966836987363973034666797034472448049559951127288464526519564552*z2*z5+1676222591290495434129335001327945080041380945985884350266966970054198338716294143966660014074516506049451071931184934733705251339934073364944061592920105105067962165722433365210*z5^2-3760918708555637784047030973057558383705258140775472893449710196036535750287271319621583118996688611385386143786446453727509659284690895960666751878053907802326935459920138914816*z2*z6-1533494821727648837647450589974303946230134522463817132957594416582059240908051669122939562199868434044119894780765127665060605223278169889400101209125144552509589032459537863776*z5*z6-1972128156521259737834310660055628309640592392919080947618323372269705820863992744222513916234344022193917607006996519358044904369591968184251955599835512796795271162609948618914*z6^2-10035720718008115266895338438750044492964280361225026574510427862642652946769723167159246667473766612092339597030141163120555033133602741402176536304089779849230434499828834094592*z2*z9-6809779198395441144592414876161019046250660792251961852432335040099747635912945043571005778157191719657506523828261403967899883177624653738710815338056623155386904808171671758592*z5*z9-14399372612052686704712326525523403297542161129933460389432351426922763271544550738545601151920450041566461081576969192032232672444554528599802530486091278590368729817197981497088*z6*z9-241274845035827907789128383358648697632886690647267592486300293142655698767771523300128531383102775371291570811062546952572950846629899910031387359143074716632713814179840000*z9^2+56511781301757359087789009135050063450708705700446831696517847573686957217326238473214902149373213864819630143704552806519895942973427101462534806124410401235378163018679355616916512*z2*z10-5983212312178988421351474009949628045105801320792228514877855671062648617226778831070386943712336607267109910466291971724108051195241433396435204075939819744210004896273398741823516*z5*z10-40775535905332069561775485208814260397555190036734627711954149979512312459846437212000888465790737346959428438585704648900912252547639024812009992957151274576690529911835809092528664*z6*z10+483371441885514249611209633192518362930285072702532272615758988439348274983102487284409934286900228783714535364691775058782968142604812200785288355104563788828867861261046626762852600*z9*z10-50635808739342302374329532984343200607904724007667120168899832153444919527988184660428398687003226776561880058820410474721617670879394983187646473233398296222879179619467477201816328500*z10^2+245796136034164237182065570845715843815073862001997828764810740125824353535437320980226181611649561632798345765627641279685670104213761972002791463782836500183830767577662762802080*z2-3672967188986136159253403215636187437528072900199216455732685741197797628079582001638764585289717187367276347034716365989347381996474470309722179679692652690888059335725748939956*z5-125353966929596113247026510977298788801830464762838593305400437498328787925038154238419907430614096213883284668322604745584948585659760341109236896736899089986852175031092195773270*z6+927641729482189414421915067259130489993851868800010170200684352037060588405047834712598921811190771070341766200482747743753467205472977610940242931857455021718063311099361453536764*z9+110595702738043459205709976129764002762703478612642189282922802907919543718547924430872459745790060609383520211209266433775507134282534200926104069526111520488193937073084393284339405*z10+1253845422582070901690791440325861325910751953174731642153526324657070579941876220664932969170261018211625376455452972055429103075446636215673719047192615054899052221714136395062536, -138341701891110328080900897914202700111007132444877118941031904635479714328771252478887171622095258691691954373952101142657084293482395620907016546282789499862500311848767206701440*z5*z6*z9-67040335862224841183416802579679548760038890890806826220324532465292394432753476656297543270423328985189445803335240298263681302261705147481438442801452528956564542583198545815328113600*z5*z10^2-154982841522119602290130755215589681974643408198928717108425683225719352434363528747528030890680408109210377333776726220798260362302012924477703400921725626611579678246636961684745938850*z6*z10^2+228431538273469893253612503240183648746369930070998464642570362226739559414041624662874673015371344015177821557036272948832927177614481579362650554321594915687480382293977227533541135000*z9*z10^2-366021111440469557507460355231644899801122461524332561423588367430357641511709322064364451404437197262954474196624608903362568923917357516944819638425833794293021464211069769202564769078125*z10^3-41124757611039869667418990301077043740626534253114426964320119352571805516233387289761127618288955022340890212222218947119511867500726475927775288529000263838417888880697608108304*z2^2+93691236596770603924864909176762466989478375188091510258312392491016495251376202443964625816102114052472106196173174286949511824839579160560384313014628206450007478559669168389470*z4^2+193417773737932653092478498594322563084203213055611410128248474132603555552808181243906071563694473060580205964127516149795668079421896543589479522723322514038740365987664182891304*z2*z5+100095732010994183816079179634364067620410005319981432997747521855525132074946562521218966377328805324438440815343545194463966291332199338752452625491001819257961933631474293099990*z5^2-257283495295845488545131022106508104408870655906269855977417682248832499983044891203199328280060902115527068844641998823599780983704917366104215754876049362986673168793646004810752*z2*z6-101988289338428381140883845194938950041283687739543124196508563509756858806129766197645087657681780337913375048323510768357380261766127072019242080444312894640996054003370325240672*z5*z6-115915371963640486885179957586406136871001478832505274371631125370543320914559670071893462824284194205367290211818569945033865891730709322792232080986487102765463090040362285897438*z6^2-608208973307956167683041789993693204567076843083660348057377701862713737345476091783872733180968869391310224418378715142806760725145194735595009049144154487002321428437998813851904*z2*z9-469423578649187219957118943810094934981541177738883760748201719724254906878909752956802922525983367291889200398121784879841404778032841693671729466679429638244178362376000514322304*z5*z9-1108347673386473856144976948186170486621311663572391617442161201769401138158870237373046753281316155036155697109506121643530579249567831217570221203713969983148780248080785272776576*z6*z9-15770119523777159426022378917818188755855997930201829900944762132109605323687689259348081527852899613925284880460905842505592895186664600733858248391634602358373546993172480000*z9^2+2997468710124432644185082794477057893066036009811121552935199378392256180800136294562916456455425692048930485737568906496314345349525852264476902552581993936469721830693016800635700064*z2*z10-347854506160114109237059672065876044123887135032978816160213628233123403486842942809747525645054824207912833200824637270731562157425879274286120259916186427674113678234949343526704372*z5*z10-2395529026346625785544493200994259562630844987326420841802127468082564829274532939160471162158015258888672909180714820070884037841422905724655143026942744457804254379644895558718710168*z6*z10-500205327058174936927963086133060977546807131899925082122936786522336972130378222778691630920924715999474937213445396722659099744088928541270091392718188244263773984489424908030702800*z9*z10-2659650611068260021774709817386214125201488957023723572839120209180056150350472956611100505873247591787812477981820474917227204765044965393426059163289398381301774276406671307164845075250*z10^2+13146701542913037646161655030357734544916722768497585748773199586703299876791647695139298568261763724107650016066748859973728304023468934065689138591887087477582526029156145650419040*z2-341110344880624777184822356095593079547400200171660140111221835223582556722621015831423010308857470748917055443836184073907905758562821942639697341396328006980560871179998622981772*z5-7438335283152305939609632825159069791956514142441514158144118663505307819690511780139471628362749258385524264453601157737260444290338636453962043662959476582374446414442536560456790*z6-7416386201235063013823360446548479058108663432112441712107097094891481708261105204163102618579846976825131468416168393551210396742559637250207277307966320343652620305595553588052712*z9+8215181061999418816851837653020356870216281199296613465192361174114236960044048849629089008510237261691098015809402168107133815629036509362073182378009716063041755803953873609636739695*z10+77274577851617121374983297941805915344171518452804656667762165639699290059174997137252183270533089029931970970661154836715219268758423211000888556648800408992858754851259126133129042, 805686836364930195310930781979507601919156525193851250246690944597367414529479471959516244490237657433107636145740800*z4*z6*z9+56062782428374241269701136504478054862235250499341053958989929482120584480471481326102705748538870446303751612670247117025*z4*z5*z10-3505122639445304735560512131670309260382757161757734025290540815332561111357866764996996020972381313177115612251092003200*z1*z6*z10-5228242041657439289036454151630494519434661196484681894968425168479951100418411313132426808641419410064971298685506115100*z3*z6*z10+41377779840123601897478171009981858285905244638126924872773904322942286908937596624680385492436321950774098617319413215350*z4*z6*z10+166847120737572556476818177535245125932774707755155686118142395125462521959694154047257407957856426249865164325432776240000*z1*z9*z10-754227447450330080904901654282549918856329875691170838800275313944089830434133852458150160955447056800097977061066664196400*z3*z9*z10+572721835878459910544348028838835446243463185788990675609275904264948394378441652638778112119462859746994354335230174770000*z4*z9*z10+19371124369743686557572562422235086885333108820814803543801248949137714966227157355084038749828026042602168262539876111796875*z1*z10^2-16749923423985706721172033793068683082755307769602083991724288943607446413118327692782790217847868390324707454197718248281250*z3*z10^2-44195509093212277831045943701719625993495889879832238522647270274576931039722470844626336421524223011249179010174883584590625*z4*z10^2-146517679979796736669557232672894219865548821073615501892399689153067510439427108088811311142391172518077989451450842400*z1*z2+528808311742878968882057406807481487444643114123119739843856767818011356547157084966363524622024389070406840160694747692*z2*z3-364208045915859875567304309069065545404772818234920737565170638837017192779523490613745822893484270760846534825479302796*z2*z4+106788407420321359881805642120842623165947854566476234310401370228147383774846346917327330004307991045468893740250677998*z1*z5+93108031858779519963506848320456389318421710601156949121771748611291684042191572377239527934017043426036376805321367048*z3*z5+47798510465443853092406449796764681553961770600543856644959454491578922276005345262054287258768398964878354699510644875*z4*z5+152533199630194206079288230079433637196682964723201143613130629132165753477527912425398760770527245303370496656994132598*z1*z6-211952916251537240625110132126658105806878426769377526560668090182390545146758671976209896970685479446103887154924754998*z3*z6+199195749773598769602906933238670548716627420758026991640267889875878995276146697547215021682184424528792699081995060598*z4*z6+598046084968438668654485284642486806836724517411673670711101347586524175360193301276603230399364396262729683444754313600*z1*z9-3198706455964761351426972599416865702353840762775744585907182724717225343833520337248171616192437250219430307757718997200*z3*z9+2535276555189802299627944326291870763038363667661539894940168724526475303131116526866429503515588562560003698659057385200*z4*z9+196636207779378939789354850598057051948623748511193086872890498060118007323264861510910805413060227827566530886365037521550*z1*z10-297530328945606324475490676125256130825489111315162390650543103695121962998549988164295643295236774431148283590470081817500*z3*z10-177642006512024602429816666725525383110873017190774361264490934888495926485149496830699176650844526922246967861923102567850*z4*z10+412848860770209409979890263701467872749555099697540972424717002362698097027355295383847341010499970765431646318006515475*z1-375439439825197654094932717540728757130177160883128633932395456792232128872977596031535722128336896128883632752767501158*z3-478484227409847357744953972918114979343875726994307250675025074380918476393822706417399255404280588919895828442255775821*z4, 805686836364930195310930781979507601919156525193851250246690944597367414529479471959516244490237657433107636145740800*z3*z6*z9+56005247225458074628659514370815252517058695490697142236912039716231744689597366518596535926498128044876986792479807803425*z4*z5*z10-3395309777808345648590136005335767369328686243609370321989195018078272274065578958617257489177658222276249811109821692800*z1*z6*z10-5126382500647249942683254645368594544398222967707081522449438141692789672966970832603152585498818967826453678015099715100*z3*z6*z10+41209817476950291373342806113456551138906881438464947409047513546902001082772783422671088652145192886667443134467002916150*z4*z6*z10+165761215255704261548613856324175347693286219558664746865359564054340946187965876180212255879144226667198184799776302640000*z1*z9*z10-757590673404771271758475240933748771821941440798984993787882768177931680829972449327363707592252979403083833552965641758000*z3*z9*z10+577218473406594609800895755598112866342132565548297337717875451397356612867003933580342004340832308196382514511585980530000*z4*z9*z10+19689248926105888460944446565895301585567417381223183785351179293124970286067614121580506915430608233168808473897775054296875*z1*z10^2-16953632687467918665484519283636437258036204439788415264071582607697619277519961510851623344860631265636956458456676895781250*z3*z10^2-44373826121106202794192154390346538292050765752642962934519790557893738101307033438433587472091173312289312951000661661150625*z4*z10^2-146505312501786396584054324458709809828401825589321726872430861779935683238749221140389854178310828158166355606675684000*z1*z2+528305977493279677156519461481497205084356629550106810596329474505923030549758760415128026758145518356155200224558582444*z2*z3-363658565837740853862906584848228121260283832350953798099356476377713701613936060634670192286522162929714557311808792972*z2*z4+106598772758616892224908297478608433626672102099168320199395889771546600633281044958010185953055720648440984413721087086*z1*z5+92889028171815162894922911596156939848141423977484171173648850814449609928501271222714788366200915137146802038630320136*z3*z5+47952718785191032779893083757888477044539407759144112723219290509939031353721157155713127292560033600115331566952550475*z4*z5+153112048659566655515230014358833219161374553088600219636261866957155086929779851962783506098127168162809662780434917686*z1*z6-211243600410549862749419780094293443256838786019640612179042531843436723619498324585835025707800832715110900988031549686*z3*z6+198068441724270036593992633656117519038415437755627428143718624961185559994464758162155453636469763769916120168686431286*z4*z6+593934860959446539424550150336154905811602192307429433828079542793536147829681807015734286105503915848605154256287164800*z1*z9-3214618441910410705615758532980544023173045427688913792266656471740605017747744136044605498326881812040499568545502485200*z3*z9+2555511730175913782935936631055912744572704740218990467867441388603934761943658204869148047511003118991410349787978422000*z4*z9+198956861074545018593988435071784487246522177085504550503496679875709134109166753065336801864095886906194294451294417279950*z1*z10-299688351146585806982881028409792120769087639882843445221280503782807386467909263980929465377853201506321855749869639475100*z3*z10-178626899563843104001461679289231092160939271776546488834327281020892372895547871613361727279183905000694216851446196865450*z4*z10+416270616200369306330197834228988910399412956231312111170932276256355488622627216034910363405309798033548623747032356275*z1-381958746959683162065053238641868578073083983363963863002034709509527832392560180522371908775312082966449477187977808006*z3-477837956906202822668810685604884665756679807234185916590626864986525573590433778216596442214710238938253192185251701197*z4, 17292712736388791010112612239275337513875891555609639867628988079434964291096406559860896452761907336461494296744012642832135536685299452613377068285348687482812538981095900837680*z2*z6*z9-1752433330899070564828330306363174513294598852649005814040530129975561299657553510463745197433835452640395923670682047717334716734652393459897412944964610635434415519663067366097582100*z5*z10^2-3702873650234937316495487242147215195446623317110676934719942864598285235169439705705115791833831257345044139831673931084713493759134041729169985960940249486206264393736246337350696100*z6*z10^2+74270705759570803902818021664673967053039253317341266531601715289529482067255227100459413004971464023236068064896228292502549668097280329964774285632522384875110924543346636925345866250*z9*z10^2-9250140751261187027755414950905760268904665512942193049718536074315978869408853207428661112767595409551836766149922473917002840313924090621706926400524888974504324823794140186525727671875*z10^3-1187020207036491048169392613680148754371298960409128164323570820001982711588021558774164109985087866106912661913905376935986296732386210109967876522190315534965306919796065304864*z2^2+2150470120717867607569284030886237847596994103986619896484443638989857947335040524644892264193787164755415805117865899002094706562853777520587143138308267476808425504523735462110*z4^2+3970388014388248509410291669666888447350156607845560522396181894366550623546078799721581009665688466813188889187781383872710977893494758133770588005975274488049372355932183976064*z2*z5+2250701737455317827037997281301681146890293678261682868949149910688199960234758775320084932618102093846660978706382326235076967362213998889638589914516670616732506077298213961910*z5^2-5386254140567925833327677763701201682643186681864884968999328543210108723402648048009776358550282611855717790258221557385927463163278815756533202795023308089707242075007799365632*z2*z6-2196145287856532609569512972530709708981514303531114040690726390359569783104306439958743622214452607282935108318897190024196927875368966932508842232083775545029782568711965163712*z5*z6-2679874586024879438523422166478399351897206871063600697210572402602490663820681629885707454907459392827251595507120048290208874975476233867358246298929367223011404076763251883998*z6^2-12893914806951386937696491773799468715517647085140058074855841025410319579395062385620128083523030783126200293041015484136215428933165970526123197256207557369127979209276442689984*z2*z9-8558986322696023518025978169857792130860353230079850489339233233492725320254634003139558808569559085469753003753244384200902284936238816773837128469729960142033748751497685561824*z5*z9-17947089070845528735970851522205542854917760250375479633787440040124966719417013848314381809187233932875873516052241661817413558937207778158997596844217696853263421012432525470176*z6*z9-303401452962733280739443684650002869973295616292438992243014564346203096346960896117008218540907613933703711522658573447605843129276023657113381413860222178019764261498880000*z9^2+79171708614100217494754438693778399845131805551252004313834023169913758363706903467011731166895124510966705907264153055056019566106874468532289436945929122830992629084404930502461664*z2*z10-8235970665433856603195619141864044057961240484260876514976469371759948918563727468004812898811688311638873707095292793308109174746606539249329383488737396411501994020654831790644912*z5*z10-56873053759527362022538852524897050225663920449745382377672921353150962604704348202635395615958995480281461696406252088318948256150178898674993558570224711004806161370069741020625008*z6*z10+579880403182572679360777163319256161624850026639055143184488349987860405412790738600810151111601143186055967937077541261624886130241848810195839604357058869894401218724221717613655700*z9*z10-72446302784270535520266371941679225063242604166335604164823927865672216519108608294197492616228152191447021432135603532202343177618138830111932293973892290088142791399984899700424904625*z10^2+345115912213249255621631563892184346721395253618522550982309414001641866269244594259195858778952240935218593884418831849345102762358660937580275873662065579535424887069732555145120*z2-4709743949075343711657227098234447025372288152895341867848973199702935331024508986220678347149692868896810249322932613280569454153699248774612739350189596110587259089927921175772*z5-175169975755143194628814106010224432609594564012073778132408066965363802500796694678356161479286719026111643176114823570359984785230525882886192386652542583200362787537786662152220*z6+1096949634847701130603484119660164608684263044709194842576481381621041640280328498806490820506911598193260925311977489955846147099051985994076048932158875349564996814644005441014698*z9+133461680210972590906577334536191091978499446172843214968547902417014773561743695354662412226744296505268903232157280122076351313779536105116014555967762693669563226557306897788491795*z10+1674029834863399618352709599218910896277403276136735013051185853140154445534397253038810774357772304390464961865951507465115744804501570415334754892488625303986888096674264558324407, 268562278788310065103643593993169200639718841731283750082230314865789138176493157319838748163412552477702545381913600*z1*z6*z9+18461274654564625577678806562741452544820180243287444236669587593137591819299227877674047246458203432402062026931537168875*z4*z5*z10-1107537680970834550877740448427107875577439935988635422559846622714057996980594574987764171711388265038532215926169590400*z1*z6*z10-1678716171412756945022213386083782030829314505406023203230395122269445079173146064256023486983677450665775811729818261300*z3*z6*z10+13570514123077159292445596566520875826413790037473111419896799759588932155367498007401166533683190765164770661338358452050*z4*z6*z10+54694707821133620805810199466556783443366254915089531060107188793449935977270780837159299120292870099780021396997254160000*z1*z9*z10-250450047276118174782954859219288357330592886045778803507718452433388276344686889046289448714253207041613409633341835594000*z3*z9*z10+190870681308111333000305475666748307104590186749859463382870315122577667899541530289908602443619568721247692739135627110000*z4*z9*z10+6529796163145990640935949865034133664018580946823587725733251215277687783797026347961831240231790205331892984779321392265625*z1*z10^2-5577879744978346871390960064407435308597489838634624462012026919806539310402356625002431851843745495169351743334360978593750*z3*z10^2-14665519053802680199193182558128670845320409314453944804994221136126922018470942565543501252925040313420899377042775311696875*z4*z10^2-48314832384414587858627944024787846897269601054666312636576311157254877944597110488757960891929862562425957905167039200*z1*z2+174129350249298384521525110390990007399969021944542354984031702736210488356748520275568530181246834008510490006696088932*z2*z3-119851976474244179423907628268430479466415171156618329179356225183398472291531810959649789183993020209207449647722042116*z2*z4+35122786906431119694239104741298503012657419762612220598000327356947038036525951435405581903805747454587455321547420858*z1*z5+30607726137610618772241144544707583121898751287616203141536634795166350256443563644569010907323000708388214950664152408*z3*z5+15835192754041342986514955088228572927687350674751526469720782742650048556938899506006248011197040258480780196384074425*z4*z5+50553161522749642375180125670806557475057710254997228085284545341164689447690298939893992250942195537146264831096799058*z1*z6-69562619973869646206278307503331879002397675880457082570442040791711062927039779203264406449700242698406484539811418258*z3*z6+65187053020985551138213738440737223320964882967259221543872878764508262508227861246135859106732472031042949302889291858*z4*z6+195294505820570919435425211917594027124007697002757384766852134359168987887733547801425276450252845435903535023331920000*z1*z9-1061989138091770437172897769121722036721917924065310431799170629993664903303085151286656251095948683899626871155515394800*z3*z9+844906730601344720595371686484818751607441725723490127584744211571355898316213463208664316199480158774010251243258066000*z4*z9+65891202524001884089971431394004974147685314647912861610236096592915188842475369639712012795035325933229428954610974677850*z1*z10-98664161382722486548114956374407800681371592100520898768264777314466593512158910928936858726960291743638447655405601061300*z3*z10-59230802821454296828867169886594211149181254873997650630390881838159879637091656896836357568664549196256828526190458332750*z4*z10+137724353737306736986900096073636427660698859360062120145950481996712264236494864032265224789550100592444185230775565425*z1-125629390458848289131791402901268241752519002083989370344243291031592999885690955895718820611334358863937183234661561218*z3-158194139712861642474852176661667695585047117609314887988922916305293604372064606910523303365611333987037940649833853391*z4, 4323178184097197752528153059818834378468972888902409966907247019858741072774101639965224113190476834115373574186003160708033884171324863153344267071337171870703134745273975209420*z5^2*z9+3287682565047707785091396511860701890875931638084849797442878842405348635196826988644992782555378029225509371789015433656728433560686980215525079097778238640507018158769638379155795700*z5*z10^2+7281369323605073727343649936895889963035822285103050989610704325298790201124436585696456047888828528150183396740447782085715057539193504565288512835986745203337678533075924872559094950*z6*z10^2-79250148539278520891410480528924325486218328227823087599710693024256189057671491655719491255947197812689648042236023754375345739861554285129862441920195601775630968867352349565105907500*z9*z10^2+21965946961767415051989722023225143793082711204259475031963485150048944616528117088826866362494694872260274431295818052262620426344690872972441917363839591774595294528717621355033153312500*z10^3+2919632884259727369928281198597626546610592755073225588652579127104612880755685079033817538702808600321978530468418430760031660206168293508791476202254011166102827181230439659888*z2^2-2699239593599406952442628353996670361197893968395370102925519790822280610360603882215614469842137455788326012571566932293053450511132090820761924695127831907344731223374183313940*z4^2-6752775527281744231305110154484966133986318786683809564428907072877197421625056299968336564264291011309445603084062510088421857484050033129573542841280275446157163880413801267048*z2*z5-2945895024199084542835405972228598614387827766157489502131812168327602500905270914087334894480021218139261834820903300838841415191574827254256926182464259479990178292562376850500*z5^2+9075391234938201772512332769997552166450059366720639718048052581898864318638434877755933564851936443009383332149097651856065427711566925574109155864707560187911283795585829438464*z2*z6+3734894916445939607351319773599239632472600190046679503416801234969897294228311172549106182530224166464844359009800432294861184499080540213524592665664962114503475135007764582944*z5*z6+3702103074422255461058284956339422310711062071389592772965829920052023871277877655992472375553504473975328603984689346166843843999256963422105468589705114665000996041029803340436*z6^2+27629202568987265251882105073879265172550070770323570383563380788943223446433880915983842121381110000025966088894613464912816409801560129031941672469562351354960921139052280832128*z2*z9+29305578573752815693860413369062854260478826553292594976438707124065076774057578892561250651226151584195532651866819644295080124239839263799295880001554884743090924623966908918208*z5*z9+32922788151490893500759294700581009091481956649845747793924125181160545861225084176795921523435534743994012747424908803156874284083993546412058972357638104102613418798522422189632*z6*z9+681976860391517122819488306495199205461683114173475852109855613137289358526075644202724570762880881905929873175988785557957777892015287514304147556228245819585790444380160000*z9^2-145891520867901668522456278066661305431599929137460603818824279134078119223198492088014910347640322341897169123834860681609898809734678536814032523810734645448333726436922614960986048*z2*z10+16861046443721718831820593395497836607138656980022242328806317762949800456464099493726236114670583926495947841518611145104746858065625625551252388505883179446592895389482522553103204*z5*z10+110879185721888987492472522513786890970195570203606140643146126837778041155150741021774180125843021784546273694450084816856360527200045868913169498693018570091860904187933907988098376*z6*z10-586017376555505390712739965926050858020375216272318545002883059672269773919908850787477711929306073001328642310681786075181825817224268461553969887650568784307047862412392828647597400*z9*z10+222144123374722668943685643209773799618249602313682460790772258741140779229387987702196463239861874833684907428493319589431589139127282804907181125157730376208585610554354155767496364875*z10^2-634495507465283741458086838694155659037745962455545951232547557206215684426088220206904145250822120691523454197298204985354146011021779780365011962643578846347067468081115865580160*z2+15084838875665468603083800745554611173690636681601403944993333849402379401613433734333792584954419410258831104706267272931272124064253457269369043792199311629726273211936707796504*z5+340366524385864718201002285508394411876679957808297711994120150366747345909570233893783230200822656091956631675592731594898041182633697373399383248792882932289786926479996714629010*z6-1005049453554272891809402926435016006932253300653577633035866756608289441462074859335719108834708613058212564342178002007852147971612625845512375010546911015586325225581934849804716*z9+371500550911430535653505823703115599718629610483029120849081146859449250888697223749204070035072174342155699092771184453745535183456581613694876566256600482747427889140799891817240210*z10-1373413551377119481753989437722466797759835261707770962232307310068007309208273624787854219352202664702628562837842421926855390262131752451028548843860819804145972584607745304026929, 53712455757662013020728718798633840127943768346256750016446062973157827635298631463967749632682510495540509076382720*z4*z5*z9+3130282154198594625685662921922788400499783289578906913150126224955136022575152402662068170330750523156927277128862575605*z4*z5*z10-173320564766809673714313921423151822053147774659461657057514419784192540993150000118561182618486407264938301230588621600*z1*z6*z10-261905906880144485762958482973428773092749108487705629920579994562894557948805531219829269762260260153920901057361657820*z3*z6*z10+2268710105482668285604919078263089294153317213244195383162712467285118935839848120160686020876929338371274733007402872530*z4*z6*z10+9599713303530651349247993490285197850484972669554305217737007913231107624202779351302730746468417254293959394744842544000*z1*z9*z10-43735021137543551172063137798238164652100743155021499809430061673178217872416376830780098648664740290801304835824433275440*z3*z9*z10+31935380897360174626564212774978518139080036088161800596690876794143097922338857772738257242066827486261904498656998722000*z4*z9*z10+1210352020556819790646110776154190749970027081894749510799559736398224184586216196595365588233077353596939594737535002578125*z1*z10^2-985261605129789972858936634855906844906015785946304561285278300455261383102143927849147503406521204400552538344614843875000*z3*z10^2-2650840011413404710562431061184684415259520814905448116427362061289220316231342001224816475198361281868998866872220429017625*z4*z10^2-8257114667234549115503306382333077177438572215885887286769992231382079912537441666152425381668775740423630812762430040*z1*z2+29307905857320268641806374832688577459352024362178222220897348718632929766432699245408976497410173208458589133200517524*z2*z3-20012466220496377877791893725532163315641731925076962256218595274492813469692398523077075290277210053158170658534517692*z2*z4+5882697368899359516248035663117931915679210246218135118629857638284039289642520809182325263270503392098878618200668806*z1*z5+5097713676905219038760666934603453467328344425521497131966032165847177864292218422341548132134048023503547855506835176*z3*z5+2846668959278479516000358289912753290584942717835057635012167586900110531948217588641758064092246687693637610625111655*z4*z5+8646230861483947391316448842972512116741396711928515713244975665361370563572239372007495474584685062994219597517236466*z1*z6-11656368052085032245191403264675194871734618266535850383805256020608104424415021720082879307632151927222519286748917586*z3*z6+10855929618863409052194050551771595686423545573411334696284456413949002858963673752156294209027187072974369559867189746*z4*z6+35130141864457599398137468293971777719793834408613296080488854057180687439003021165597303380268298423084272943397195520*z1*z9-191710964232530935822444519029407319296691857555956456585229158977313506438209576051946422026162558091509695043589320080*z3*z9+146815274283783916294543590074162592093783231509261862308734023590546191156945052744187094403008334898617008468435742640*z4*z9+12051948967709635876595128844650461042490364840660541911445818330586818253473862124111692853088909294981477620316440501650*z1*z10-17583280124004616585294606129742398680112636506655564266897300226337638897019815370578076529630772174327552840527402534060*z3*z10-10971415599870055801539738895975156149652141122128325857220680977144423225991881726253147466824556083914292076558166606410*z4*z10+25137094532735159951799545827974664463027330836538560045175474594644403913307903161579632100455582271749990780349712245*z1-24480900495968685575935364884594974108055027827093206841129378034458036135969517390853924346547759855995607901023209536*z3-27501432265688244741233227411460918883582430980891028585259060314178381538056701695919330265572667390408489692201947317*z4, 268562278788310065103643593993169200639718841731283750082230314865789138176493157319838748163412552477702545381913600*z3*z5*z9+15825263244920379272376609181048362390979319896974583924090949713865169852108529665034289225274997751023391428927587911625*z4*z5*z10-908815288218020332808031214402114728658323294517870556714348114976790132030469047924180603630214313687457969172114205600*z1*z6*z10-1358869183200672323538563903390436409809166487824526828628361085841303677927832176744756467363922500634593858903420961100*z3*z6*z10+11510384268030487110007972710719475219675260430761214713329157802416663547547271395009881966058620052464215619819578583450*z4*z6*z10+49128153554827346657380843094553225077466362865686793230566621464925019335447428600505784544378602590020645754553652720000*z1*z9*z10-220459193145718104792057147908509945901952536495427653861357632438156136840877155370500207336762608727734793714126111362800*z3*z9*z10+160299925618580214434760364810009432122116064254402888490300764405976012469114904637192913751406912353148769049520844170000*z4*z9*z10+6030606853842835598754131743035321107065933705188250018070065313174141367542641051175528250795131527536398271888987057890625*z1*z10^2-4843755166726813341238976148393964661512139625426976473756472906283081185433580321278797511956871235810894534188581104375000*z3*z10^2-13372108513026930889066868187468506210259089120000325060467568099083905764300722910660697658994937988791308508409285203888125*z4*z10^2-41689086366837150129088385509844371370708455666623076501002659694477067023894280926798377810087688332470310722875247800*z1*z2+148162120989830434758763684628223706506180346551089038182936017054674979070183209285146001317939902862460143114493679844*z2*z3-101210120578101621661120045006162765596129105473091020108577334317337834677997029710712491759318458261124759748982028972*z2*z4+29767191436237986210159718591389240427775176615521594686368376128454201474699381545106429885864728198463342364456048286*z1*z5+25795834328374875319477487991521699455075120731318221651714480711150022809733876097150924374147731790895892758366387336*z3*z5+14342187732774487249615170295661231741962603640017987210250650741774496315616204529426293932029605706402520617245775875*z4*z5+43487851158042252025292043829311609951408138760583451786402201589299831210173032593325035886719246307540299503455561786*z1*z6-59126249566065827889075968278261202139430952648824294035923294912951754015502120442097240226523407302454318882725954586*z3*z6+55173635511045256269709253548109887835187279309905284554014698277169023715340973166548534600759164258827784814846569786*z4*z6+180300545793466586146800133011837578326426264139024677979281518941358702640462723913883608996886731780790734786268076800*z1*z9-965749343855317847204173236224530072378019585248070129802910657383442215154368414918039224052299641089737525616488821200*z3*z9+736480575176084431364842683052561017080457019658901273369337738378767651529282152487540751975805370424199894659435698800*z4*z9+60311165006429551375132931933554223100338796014405795853279497974124008614744149823010807288945689050282995764250167298650*z1*z10-87155441544185708759990789669001931803716990830046788908274473588880869500702614476899693611817708069234433765501732663900*z3*z10-55822634953243466433815568690087815640457881048091817010088477991953827583504872545169302355662184042017341420713726529650*z4*z10+126317801583053281703247261250667918042065940358770166669576499848707061203145365743571519896250560875660165119492889225*z1-118629250674081895856740469028755489370266207630352013840447588430408498683862937514080203809364130350934268424561344256*z3-141529026683098553315500098339559697986055359860140679121920996877886667562064393896640238272067865342676895399169426697*z4, -138341701891110328080900897914202700111007132444877118941031904635479714328771252478887171622095258691691954373952101142657084293482395620907016546282789499862500311848767206701440*z2*z5*z9-12030438138367564920813022157996873038839651612169933897602576820943779937209823514933561107717557285195480230090486106998289011554948534571280434285152667723597369952936311013150203600*z5*z10^2-33539403226153711509219162036135005660097045218561420374060249032325663992800546838334346479184585297930835597157927617333519063746221037489107785299648968011676270063537648265798747850*z6*z10^2-112681701682565830627844902724086228967053771471867963994563576686508450993611473136134205343383835721223264106059224067275013109395623067424145625232124890539617242360160888809429215000*z9*z10^2-74472844444163625073823027929271087146269345202647749916978224545509936874697743571038875106196535814031082140894445139936055599186761543348120484524753452354021127609759837837085174453125*z10^3-8130459594066709664787988062947284684209634140326353764658016532785978559693796367765770582014650155218123255422960817608525043002431931866565930127834778083833082933017854630224*z2^2+24155122022156647360246762797797505252347767526380995160346032884416319437364077062676362739566946891863594293367006930463535684258095065193329652809431543698542238931873932781630*z4^2+47173165667549569360606731405654521864528885257125189162707261866701994598353246450853389601337839775647487445220469477384275209594457717868779129664922957790008093168922032422664*z2*z5+25989708288213195058419041227046350028579582303783945093424044338826165440251488308301474009860173948620088249794320247141307412921659848878981237192560035115892851979858462614710*z5^2-62128439516658800237697930403772147453545248752218667199904883033440344555132553371953778802998411621013724116436807112747809050203662461985484907844410810260199072225280268035072*z2*z6-24298611760868522203403831278257011847837914174915132134610659798629801418600830307539903957621112090767132293624864216628861214520873926440962233088982365805442019307600565094112*z5*z6-28956201110797789631106848048934150761467065106369759335722073715243366671814565688246589413404987650344474641969000393245015975233470112084889627815659944164760769573076825042878*z6^2-279408617452262179912390866505968670105504188554853769652395632231005954633966824175692110720753288531463103169704634111182441706359810625547649038187926494995896583926597918450944*z2*z9-108069569762184511452978063036105011043732002145299998563188501024636127589593197071441903778320566096140771661754519757317795091708169176146778898649773737679761889564883760052864*z5*z9-256793029559741016416905361660772774853428272741934861438802949853406065886733358958306671614332446769464028688023657863394068160142633984641230125057347169977101439842825374983296*z6*z9-3617196098793473473741155161185930443818722531193444619788913926224894848746700489600864963454481669191023581019915954970648069524572450238286268981096347737631384707809280000*z9^2+611456813227672233267440384707961701234103185777151524355864887910104448437431297405429743418129979804773106260780357035868175925421201612082770183511420059852742628273253812477123424*z2*z10-53194612603033953510463916742487173387809650627708391529004730171333493114185714286906906134419644934096451818779251981507795710999976836989780577016633182397339528483033853129073572*z5*z10-517443267318131039776220354242296519112523664219430880714732744541217903028346815091986647114029302263232459942488288865630267751311499776357920279968350216226585343055530061090074488*z6*z10-1585814738649318665313272332200081970743915782628335941075694247785816114707922537320833342889479396342440956901843030275722894435702966099661131337004485761718443499423824935576650800*z9*z10-424001889514663268601844926594158790968245363197284390115830414964125192153779031949233936474582722970976698534074037351009622735120853423580689641323634111216768033136557191304193176750*z10^2+2681933056491805971515444143700058159452016983715908797445043417903856055336642684643491618339074781724340504983544459804520650148956055155757932276859082014419584398422119045341280*z2-25548480123769713516564055176923385824783422147529026074389330501446361110922031679370287750098667893667869567249944632800589887682713286441159085142656997498199955436502629036172*z5-1605233819090013727206616456180661860189828881849979044581313745075594124587914794717204971711509561831152037257325408166964318506728629274447143113874617332632774360089374216294350*z6-4978768520994377253970313915810090854440983758446110091903327278526246227259946053863242313292806826801007630711156807701212836723600250962010637628581993328515256010195253291293592*z9+3247733578347352787119427403556216637225472276650823845400166912818556103379413114000666691400399305232866209996676791096953447183940480806532003178692029729020167542313631571046396415*z10+21549255380238245468669823749329845978671307787190742007112632741095606782788308641385635170857009699152442368516245574741867502072414617847399211825022108689173784330177403005731782, 89520759596103355034547864664389733546572947243761250027410104955263046058831052439946249387804184159234181793971200*z1*z5*z9+5302542383697438260718343180946791264972155933190755903802086996434925232241801598513449984482968613365954905102862714675*z4*z5*z10-306677255828966409778004600236071364987953365977271576077430118398965817995284695777814573524808445977565241663845356000*z1*z6*z10-457169689839259775778510854998031807177357588746190699303976008726388994737259185962883873875285784564836071230613258500*z3*z6*z10+3859151520546794560944501059922074760453801907506815564476865920384942684253879905211387967907432931466041751084386428350*z4*z6*z10+16415694933788611880791588402789010100526887334448631606208519154326683111567583051645373212109239036860214032369602640000*z1*z9*z10-73694332979653455460931358298805969475499722216870164814719327891240012385272284742663538055885355299870166542757216178000*z3*z9*z10+53607907851171199561467517919091670200757976510496936654225266677898187130851255205922124383139919864300069125450798030000*z4*z9*z10+2011931986468039259437802233079736745218871024796736011543306920882458787870050747472781707014768400009960881641799273046875*z1*z10^2-1635755745381185976358368416709202519992885127979160450852071050255452294287907491102830482038171285340145994172889258125000*z3*z10^2-4468077277250565059617420153433713246860953995554738412666205161371701609603534206995891890475639161873246094971666149299375*z4*z10^2-13965573189217304592297549038779903055437326396769984245210577316353801886244880952787664210733347407752179598132164200*z1*z2+49648691485194163447901429318606711262580140985559079028645914912154186791994327531361534734109810407846572283959898892*z2*z3-33915761064230038852198097447544091914852624394271815002883892684800593175107116459779629330687898698193211359275688996*z2*z4+9977744142959599155282733610695314433858871982974244792276171923772924843045082842624099463955480906126098792080035498*z1*z5+8646299739072312611568608239847490098029120938718127487494970197996028846040616862248455675569230323886804615367362648*z3*z5+4799278084075947090006686264706399916688385117120519338648995697835086573553112113456504237549644768716475515147187025*z4*z5+14555837561257397499580755975194767588563787290028757936109480617713562758066746973603513317210516778586363155217418398*z1*z6-19823132765313705549562914669003010489022332828532430197777178186972814636907479991218611634990183153523340108402759998*z3*z6+18506056989768176858819342082137858088387276582500991014644525484337526492341301396313228973421708986585697525821853598*z4*z6+60443302064054767834139671137273922614460050225983940837227107451576801734983820133953824794588963356193610680266041600*z1*z9-323029883909229868945322776566959936160245809345571529047091621805082367392374802380741663288838760615428243147301250800*z3*z9+246291982656556389565831216554043000109589862507170840457782611102329070115035135279311577809222296221700466859783106000*z4*z9+20136529836393558409997512525716258548735819698283112548971592217474247969743452701374931515542891446024787736050030682750*z1*z10-29360964852175134095689809314935859615235993810847688480828518599899479597635617177120348483977902993914225178223287496500*z3*z10-18550805226045911033470764628870498552965949448179657135795092441443720027854962254906048066149340712721580767158212857350*z4*z10+42192831637465208194535623471216330768311989845915195241692015083504135298652589102447536753178374618262034823563564275*z1-40185966234349689088106126979784693211968815282272653714352464168730423574002962433350168023929077427359307447651982208*z3-47005498744653096676639778075131863860005781421220962278745556067862028664848584716486199127502126761309276342943869171*z4, 4323178184097197752528153059818834378468972888902409966907247019858741072774101639965224113190476834115373574186003160708033884171324863153344267071337171870703134745273975209420*z4^2*z9-4965510890248574792997578798081830474948167535992752908425091156031652896376264573707190583320909347489909053160517712633541249283540094536459635530740733393160012129989153901341571700*z5*z10^2-10746284006477754661538274109924518272897222401454381470774200418292159224712207090638201521512543945832709079122309941516330040795139992106220433775005533079587593621406007084801651200*z6*z10^2+246192184993767279389377722961199553779868820276486976404330694886893551397363559532115756528736339415129782021831544804463198891981549800494569299864872058042540100447418572123386545000*z9*z10^2-30700979177959786740141522223546945437493945736880769838407744623461806985023825581996016045541014104303406517743118577302952880724825126455874698640618376425416473319554262853338454859375*z10^3-4211307383081498942283271144054494959127056455384713680971726455556791243647591808577888203057265174122756805505565915163046501898005823299145603729076351540392810313969246300848*z2^2+4747155366939846772722543635824532855091380718108858402142237369538657340015401884593913386122309437224853687824969991025967727084700366102279863991769013989110707712344658796190*z4^2+10010318696050321106246175251483260204389022511722297235201670557120537180312279814988571166132736850767292962690213598553673203029399546755861401934091502148160267833865119087248*z2*z5+5106744138642805370675438660601077298143781282690142607626446155528647684921412253867191268029414997366484802995331881026685782795550845927858396372544014715019389357093288839910*z5^2-13533388458566128356178066862226546387529130624538629304927288479987638852241130883431415660959977094747228255020271315264965877712682053764946005998536723772936797650622361001984*z2*z6-5555569186859169967746429144713587102276123013865896384900683127380621179418979936749818272980955221631831126219664202987533827528724468066071660609995332354844287234466099144704*z5*z6-6244518226523267125026017278271204285675808445148159488285785926042747022684421965683008610058982417835539203990430570536976859553592350374017133026581029872029490696302474521246*z6^2-40935314525619962296151184435070973477363187731981423096057806228164242004744676627445210720440930588956503166000261586685412097705369613414754212868682594783840677352096491047808*z2*z9-37656174294512205963172573428771496691341990364338926857547976092919198438857640919737216794012085406251228860596293022027094412715824951482368621876900161221418156568497466741568*z5*z9-50824907924048270264600067846129941959063749621255385342081537248086775346906767911531843031668413697867771797287549541940209627850840152448283505900295246950142404602438095046592*z6*z9-984868018240715854205704382535047465648087239462440007253273457032875821204140016026023884688873399956476672926192825918689928924905781258805697548534587480994117072117760000*z9^2+219001507339341825403459942373652934294824842075821053281500557582012635815109746939767414406053354488746417812581401505570420590533964874889573186200012149864969007704257346780319968*z2*z10-25009722212011391039778076695810112009178003916826888239789949202686630274195541152318233160233330303505022575150581241500378239624757927055317469722674407802216148636693587083454704*z5*z10-163930378199466578731143556712851565642422649010126799474481537293291236044087667613762031770560801710306188228747554300271213819676948479073138485516097132063476697661399468044908736*z6*z10+2417445300892819155874451480739489116312593398707920872104371311333390224657089777529181496141152654722327547494604733050972534248490397107835510782291961872113189350547524905632615400*z9*z10-290032383382310420034366053976174778411861055484219182145198219355469915258401025698183353945524843412948349470038411641555819731844941261051159148657946345626625050477518803904900733875*z10^2+951780892869240550130016422781783402627313651656641076358872239654335529875706320811568111008755451817985172699325399090402601242192134337434063911880271462313087794528128518333600*z2-20634840045983836902299348876708157225692914890606735226493110098579466251015024926848784996964096950199192037537512583490615524767053159654199870629864786223603386063254218075484*z5-503125775067157436940230679517105061209147397794163552796792046897845376670507556419702684163950052412310223765256560084313273761717289883351927239022922162747628641998702987716480*z6+6806630168552256089935451046478105818083482253413853566490486126037404188078293432483168830101234539098179043567011345393000733258552124805245298192914338303096515889345057657722316*z9-238657112243499280135167665484576916546715297664541984214067177998615666451925543342754032906048489659480168021363149875294558517136529461090396435398131066819753935313269011911175965*z10+2977564059903506827424834633329791373207280582414476922995804888556865475089117191598750456078429864951790155517231376617137549350639292913352069438534763546694445547722856842129549, 3222747345459720781243723127918030407676626100775405000986763778389469658117917887838064977960950629732430544582963200*z2*z4*z9+98645281926638654716589619882151134974459277403528698573383305984295448081312450673243885714634139430464472406218773644025*z4*z5*z10-12320479270007233037759376702629516016529501310074049673476800138866625840975207911896399269991304063441583334762292818400*z1*z6*z10-14702816118605125378375913490040429077326492686016739045049070821054358044829630869027878995175483131714935640312654793900*z3*z6*z10+80515877621321258514975632442588428219140304698005688847826177085932292183906090959366820689357442887243777082173034226850*z4*z6*z10+302964363715910512184538008436498387213131948494758717055660779547199386463780451677028382337907067307973125355787517040000*z1*z9*z10-961673284068881597741727163339959735626469015355250277884933890915276982897626939273405369774640249009217818771782253377200*z3*z9*z10+663108121799661404663316475912784546674021000272122032119372530787704113599955802756968450075440464720892159053637666390000*z4*z9*z10+10939272869061046988944635324195165373550073851228865134450227783497344514155483917469861470189295963488255644239372830078125*z1*z10^2-26153928309141800444416732422764348396343498019573089141527275326117645330605983831072844026792828218571079657521516709062500*z3*z10^2-55330889317080783877016411952618488870244327506968481107995061728691909074505198659864057134298137719160899467673899661423125*z4*z10^2-247451259313880808854849435845421341866835853879350060936817313709861357627680690910019423348341676397005139559331975400*z1*z2+941280880497245212659024965860675282885933187332130609779826226173491677860118032913293084542882164971805594347177553364*z2*z3-659655305072786226482096849486446146137780134350818826274705186861405751750312991879064189459114772561190010145927892332*z2*z4+195768187822431367378496745134287937492454088908636316498932942202678818083104852263656943698400920889209196745404178366*z1*z5+172551026458189436720334375535118294925519928511377699879880045043584505095051990480024305516119314898376016371356900616*z3*z5+67423677937061279020258001200384060289020874953409269383796508813241974034455752936346397875330148529206165523848102675*z4*z5+226387241925170411823790346478441189486914625667391915408489701548175741026383092096854264090746046487063095541499444866*z1*z6-405335214399071942132561308582912466743295186882043838527948822957271599803133425039079730771497767762943131797744175266*z3*z6+406456358709938103242899907001322692129477343239059090780787398080797484797972330958881446301058160347156576767069140866*z4*z6+1025752734152575409103542802158111049929451344279085870917495700945535822320721587531099737843080858374338369533381056000*z1*z9-3996211336217040566580475992067772080703558416933236704160995464527417221546295330823365968154798584884412902688527350000*z3*z9+2990093629979977010523085092179964392197091561531537548896244140277424211569545186354518485009366156138033938673198190000*z4*z9+165455170870593756842079001886200683254050519587697419704999135130476194032602522477131972933322594302632481622580316244850*z1*z10-476679813961668008273826858925267475344773054039404745107924140931355877136809110206484750230309559771575931343179041651100*z3*z10-146658998375956856158616742972918503457249504996973844406448058232056149248954721101130342146461304444255130569411997056450*z4*z10+421711337730810875672569588494602882134253716260045176238381451065940298325487023620249478162666135171013988999003553525*z1-488580013588481408150591856377607650064695304988588676109436890923331480128776833696227898968047898076480155126076738836*z3-606432974556132593145658837764046176234134731494956944562504987910001731670452873297188353345584024961975493736964178657*z4, 8853868921031060997177657466508972807104456476472135612226041896670701717041360158648778983814096556268285079932934473130053394782873319738049058962098527991200019958321101228892160*z1*z4*z9-26114751859269617773447607779871850558019074478839443201949159184611524085089900321336626093869757394895898661288749484559522986575450171665519302686892785058558290500919589774821760533200*z5*z10^2-57102525340427030415595137656987774740148446703725696702671328118401826299146822414966676895463562890948897220869990027272304183908392172623290217940535173789484440724509047357117844970450*z6*z10^2-836651162046407336431931379738440746025460435455489868144480933629819941606225800448240262163592856993185420894586842339200464041497889664776992016166789502660981407814751246588678444305000*z9*z10^2-28355847131582265497901971217098059053181895717605676613887289800928867125995879276775664774007674438855523508309691169823569391582235430251125904078500620067285072847907631454391354129453125*z10^3-39552638544310084654322993812784357810550152921217536607586117110587047198533775376878086472778731999229234186037176852866232679611149808326327480509874719729146719352051310276774448*z2^2+553366807564441312323603591656810800444028529779508475764127618541918857315085009915548686488381034766767817495808404570628337173929582483628066185131157999450001247395068826805760*z1*z4+76062779383400491140658729486220206204462215259081329341532778705437554029270027721953828559140278199659378107868347840722237678698568583106748110331868461258546438066375954440395310*z4^2+135509362085912954196884722182877077826299055041847048696629773466874681917374068549301743205934126665147744752636280490487533135169396748618957134114488086905508633369017629743178888*z2*z5+79984057213894324252699219205715406845859144749575725333101335976500447889319859285500298466992220147385700700095722850523117857669223090858593295852362161993918826931534472707619430*z5^2-172709575641555002495378633043336775284044708697263051458564636607537098983287690590911355509464588407006391766755435094081265993414018365942395973919616247107745494014952960703985664*z2*z6-68482721839124312573229004702475128996892694511292972326056184008851364234162209790611418950002484149421973949801414704791217229554104397095562988210446060533674389096457703938551264*z5*z6-85540202523779179034543348659374732276925849474259313090446774601988885768996457906014157168688229676504778980034481630231639253780567883612921935619698366594550018467270809366064046*z6^2-320991048457771410522473534462234684649242798614782972764097896764068562574516455782840083717964662188624654283387050278658515567946699281177833253866890310489391108995361971358802688*z2*z9-281856348788573292644592254958817370158318232051461879985184887045815829426853680944476888671851186195614398512014655238200534603316582199111606865902149792832356433238501876826051968*z5*z9-580587052272826916216718745593342111846163955279181976079821420319896601777603388967563017512205530247369447721511538661139075678224846942097302972376618654914409328857595729990673792*z6*z9-9473263263777113705239226713030170837834956532494449871227845631958470192663377847611196925697909990805767831241880604037807257209473719563367331430940847713643225324781813760000*z9^2+1291966758496451799583334862129200862003781873709503839970203722389188359711298862659916971953980703563818800310493719405608652623676884955905148376040655811114539942877159292159915271168*z2*z10-112490215822809481273762064609105781245458497798078232993819685888104922770608513207023150472071776116241327019465400631989267288551632081187646919818533317113270123364612869111802116804*z5*z10-898588043308476770537501105798319287911087937881397709632822570492359952102902793482163785174116019470680113446304449526727792487679914970196718445390075227479110798738988995798089312816*z6*z10-8486255526117517390862124982512362055150478776283231972690292280363117107702903687666900708711536033718877558529521283131456823367778181265267467799770601412272185476422190693145939707600*z9*z10+1268308204514113895077464394912187000085121363260931743239496365574274257658592085555590630916821247700813349381705529196731239314249344471265477907855339656756311595237524953532112563729000*z10^2+5589548887943088962241611544802348059553444668634867671436524885650018348612344923125203261897121925232690077653982187240598283043833959355978265246370252750707848154428564277208798240*z2-55265528484130119408723658359994597289704262568923015895914433036603315200464027394593754782941751243004205401876749933483111743452359458933120208576144529957374054616082070505594604*z5-2769628479680717488655891466353104725091855305482073260275012980176634896076037312878449949006715514737406971390446033300235802494274694859959866106274858223863129212520960798488726990*z6-19606483554937980840336596639520377333354811173713975624073783009368790351620378483078548146108555378914954067603489947283089489552581799028720867870259537257481853197284729356582071784*z9+20750074229717964444118412576576519684296516051674243346579918012023985503437551478276321234841771338755632955233386849276056732621529073481422036787906359219861070638273020301462308465355*z10+81494727406854788914471056510518420779390202782901622213476160088501958564047357057112777883244562621000382011104940364598658562329450811805067735119477710989039363821089879845840330604, 92078495584563450892677803654800868790760745736440142885336107953984847374797653938230427941741446563783729845227520*z2*z3*z9+2804455631212723082677487103124271952671229529950397689187816520168011751056637860815789223332102984964104047889897365475*z4*z5*z10-347575072648456011671364024752772671215137186623339034044313519011215461262613286145456390801836488587200566355463831200*z1*z6*z10-415449537647570900592488862064694533095934478476661084291179863211827301637636003210835626130185488686461379387852457380*z3*z6*z10+2285987040144976561591767135110461912361575614603074801060890188333107819184762927371866134410523159494477223164466755670*z4*z6*z10+8581248180627542884462549727055588709026260369217693714390521671844085064787880498814328754392495024115503197430085072000*z1*z9*z10-27413102140394114843635063073666022355377265310663753974171069857532304464231507457717147895442399725003058999002437116560*z3*z9*z10+18960810516106410245410751642514881641695614563509378294768110562020718878562262393345523832496214566154089968111337170000*z4*z9*z10+318594216678690813931653930053015754712056840195997217651246520472408964076965256879501634423865863941608746834746300609375*z1*z10^2-749658660433135990439779517976322066516522754617973504215584702297741405123079091599777101810817816983552770518932106687500*z3*z10^2-1576782418260469093372085553906913168691777245849506653728528206031208392931702051096257888293670474782908016425805508524375*z4*z10^2-7037602066068884396754450670100870272445162653355519439914304370593944988647040126264077241164316757147062038678549880*z1*z2+26764739678529236304894686390098106338645621988905670919735468838041295791922499202125097817691747608905439665611341276*z2*z3-18753191657928230080997644753627506868253785638432151265662348802068246359666583012668364957634076469858583033090274788*z2*z4+5564354604870591109201292179207847011540983998820438818275621665085665563507683250762760681878365761090911455456465354*z1*z5+4903313737818412288587544173968984839748192123451708589611587759701808553711886148447330931856367870408077836312975064*z3*z5+1920380399450898885741711240774668506411603557752060413395718396300932498136256911604431775710332603450012353597529825*z4*z5+6454995679858064856082555539819995183835231196811809346022090723896471309537857273764926885015508573696099096152862454*z1*z6-11511163404739522517234207180006272112909506917518475761092972548914740353653004983976814583633959981169289535544972374*z3*z6+11532557708402805354272207487223273170008043514464324781203434341987841113479289926904024373118381609619203834855248374*z4*z6+29019076006401926370383266204610980042908691381789408381749733327518979302827891482983222751615546580840322510589678080*z1*z9-113946727972278735852822385577365678554546985697438988832170158186368308718014920182247795618622298573459699252366493520*z3*z9+85503217572717500392302378120206445920581369198073422143674357845386806661580611036848976951769007425392702459563241360*z4*z9+4758576894582519378579067057423316132170750821311659483559964084734307953394942403575513416346795683948098964903424980550*z1*z10-13617253850855619680299957859917924443187234335853406785565135169187084215324090143381308487416294465907065913459205745140*z3*z10-4184061864746522645421756371408975523415581201970509033658485590339788441326016936291506221554635640350365321972914321590*z4*z10+12063726649771439715547493950299916355079299134336079874877026669754129004721620093611223434299656858440500890322015735*z1-14067380745626519537470103335950658416042701210091685920183524745609835860108719523038254634958099678061234183078151324*z3-17206290497415716652321842321832064746652190379487647025115265944313258723689162345061394890663161548930017109189130843*z4, 553366807564441312323603591656810800444028529779508475764127618541918857315085009915548686488381034766767817495808404570628337173929582483628066185131157999450001247395068826805760*z1*z3*z9-1885257393895088723591247484279177756135818248189984620792003677174891969423044206987091420910880976021870253046786892220587248927365174041108556978423462547765871459564396708301776744100*z5*z10^2-4589446970529685064533263532615077222915594127029173318030019456119102289065372354000278261759296355259862654271254574538310347526616392874983450174718228935422295926027937316433901027600*z6*z10^2-48707249497919794081795701810758196499177018492675103337392450162620450299887896190260433796688993384034736039266646060931284440681594073362020363361195431617465737854920105345288743996250*z9*z10^2-6980288074285019062941943283902030210409403560029171627511858124309110099121623895868458823621198365759734362878246931288733686334605402849540034564990333447045828136359925774002159824265625*z10^3-2381486093074727334718737695073670187309958882605455231342906675051813020612244142364199147988623780810712634456064267039473141366634444289787557769182728954649655366604444979350784*z2^2+34585425472777582020225224478550675027751783111219279735257976158869928582192813119721792905523814672922988593488025285664271073370598905226754136570697374965625077962191801675360*z1*z3+4582596372837198610660036106131652048053443351694317590259633145754757405241376505816341880287187539417446100752401647044052547612283073518566983989743615138366817542034698259014250*z4^2+8743119866453009924016035215431998377392519749579734356801088872397942602802044084844661928001136819481723900030080825941563513195981827554216219042943365287436552678738699849682864*z2*z5+4826824030252791263502375769288891689841511010809652443886012238656485450227813398799231545542126093221047840296900321516586644893723945815158568062844344497259856638546715467542930*z5^2-11222677976004531493170377000937515192731456677973307282031162803164703484314399473964247097513860821129054132004866885810692302848138242790687354229945660064211427060317391273162752*z2*z6-4498123065874002810903545285281313873502535787074337888449548685685993180153711927756592153019411821405393235014837618832735330677666352570480084808907646065618875230002526732468992*z5*z6-5282136871869366115538740162834409688183422306930518622921261456951994028771681548093211525073070849150153588988507964565258904311578095978401928779183995525025475386886243069174378*z6^2-22112569076060244714841262198329812934376084597948568233528589295707527771020068266327043024611381837203754632088368030608290473676193680877399507830796475736772229744068127133660864*z2*z9-18503536974583185866381151325544341714363076262595515515001328079561315465166279943190885414221674676478172358576475378170287652070937996107203703075203369562083687375667516182862944*z5*z9-41596400218711735789335950225477610602850187472329993296614393387387343548505115843045601030592887240626585846572250831979593751880712067977905299270497062428939437027749763838924896*z6*z9-660544688977896813700353301725844579772990062160924952061093777835430431021363934203011284624331685400938691552888928736744622663198114084279239935249309574134925161609850880000*z9^2+102366427243394408187152307708954297618180770253868966701470144177652716912408249135410714656040560898331651659130931087795713063626662550700604383094628700949600963801029233801622781984*z2*z10-7230487586677827798296187897996981912989436412151031501194697876194441260385290358897939781217190962912784095610054005577724070906932871375395264775510733652227517251557024139553395192*z5*z10-71603969151592236168686675770799994057408147700601003763877659014362504015493504775422697687773178857121792344843103777769510859733411023680063023980180272840271485118915584390045502208*z6*z10-535175751523233253931385387222569357494112777466980484335084728847583801767523303066110623286163018610322435158451631120339755500767507990439036334701632068023628508451580247270265269300*z9*z10+9160923263870098797133420578735343024305639201930995193619326570445528837187183496157408595116152227475144978202258104283224563254762335900465524530853421219046491243505747806104720065875*z10^2+445512075422838460455919229716915725233203536765990664545020200451152862250282744391714442484178981350221458515043895160167499321690736208045508075743359067564382931315071692751627040*z2+361187787693843952527706220760036710993202716251648146365880068315630515555563092183081823467542622807170724650596829988317665599669892600686732241202341544290651110628378154854188*z5-221175115111980700545484757884073583856550293632467015991825073407969625790944974490026677662814771097085092872370937113473048345433962613242629411231776209844624379355784307366181120*z6-1319811353838525021232567489365323198798291293646623668865082509506642563004563859086373669211894772247470811925143431516713337803070985518463337879408595480699239727067865055501387322*z9+968104375762291432220841241139837528625485958703966333542662607494390910597700168003170553263129585765541588804395878623493759497851826500478562148615141136345758928223713116429523983205*z10+4517487028087855642295997820073688849545438720617535962129789734723692252282573748286649752563554176135482472571789491761778032086554706726581069236850288898020662674460082338888583227, 34585425472777582020225224478550675027751783111219279735257976158869928582192813119721792905523814672922988593488025285664271073370598905226754136570697374965625077962191801675360*z2^2*z9-1130201573489923745978910084821118490145308536942747293213955322451539644844687362483942276524810647177783946663518634249736700124336671532896898606153761798884978677669776463325494700*z5*z10^2-2399430367901723954785083816963830801775902416086011891703296023009466172625975110230483934816702288964869993179328101934782461669030698512339384642883748388217657543866189434444658700*z6*z10^2+44607007991030831363575528218742891390969983185983744597766032780352826526836467791995500217176750139713072743174119596110328037851397767242293770133517374301467089833701251792511795000*z9*z10^2-5888275014748354238244317416119208755453476439462842788332531534680318855227667026823152703129378541954828032302146092330050935609594092952280601872391878667457918821595611469779087390625*z10^3-572469262632618508327694355365915887115530024375032379030696214387399618646437900498087811557385531773467733459415232640316147985389883315435755324039510250629566207385247652448*z2^2+1404367384106549202984617056164937942153949974957471064676747257956516529546030497722473005146854818788933105084212501548209441942417694735830999938480396153118592294413739057930*z4^2+2625890319350936123363722018183297854935813654175384661130815164466327680516805168540643524992388551313248205729460653280433396491323810706871160826531202909833864566182232121728*z2*z5+1454703488345963018362698063532534904303677826983188236469919179440105520260037937834101938797009457596704191987752152606106730200243567866791528767235753306170140531434418645330*z5^2-3660647209262826829323636308568883123435178795253974144594785552639337268078868027148654046656741008726176532751465492224677267314315350500071202451287932311712089911038530678784*z2*z6-1489642462433005471325970197893464520674809195729064057918103570041245520097037994333962119118922764566641250878429410378355473722661416692728815427076180260990609606998608358464*z5*z6-1750176095805638290293023779256645278709951259160757195720877613758393454058184334273794772509160773269042039440947480217752010645324815937885950971299908075140788061671665125386*z6^2-8032185689150339431907891516104132838569977386860987412666134940083713134674743818527727404197451091441545934429525204539323832289225734040747435589903993016987452602282315009088*z2*z9-5188176842617109703758851712099889636935888593648048916376917870338297816422719393047586693403896357928902893001618956280830581132981260817281473753377704946710641815218612685088*z5*z9-10661337906891061718060819993820164225101817541654377770782483513082833922323072788133232799676058860145426323669631052461262956821446693069214207829751171435016549440392899902752*z6*z9-182496742560873535880157252567082174645421718238100023718107443720720257646069461620814640182259177285450130456409269727222689298281738585986390036465259868593020177960960000*z9^2+51616762404552435186092067750319560962242987853351197559356178759315224283787998458460833634328324338614441183095408868315004197963630805800186539520145630596564897958347327234555808*z2*z10-5253410144382898595857239553677467644423155080262669198723809821757172357402380409453296515638763590826059615242828258840185543413644953402354199483293811112945336829618303454994864*z5*z10-36932256986053352958540546695209784832437280700045675699054381569241477116245399814580630266265236938866096792377083802074000695876346399668489929217634865755557300606722392654668496*z6*z10+346244316435290464856641999095259906015705517677959406479967077043348282217368063550990247459865842143025598051850006464257957624136937236075523468994247550495794130994751282825484400*z9*z10-45265701820840188593493164871002598392942954922561956425025443151895082225767861703363997669290994766831993802190564972414349062136990834825423214035887551502394207286403389497229690875*z10^2+225443839131648241507526500950703230002503632265733372798602543624951683023083296685238994832070334309682440462735828052390781540872327765867891383564365004445075103236543286289120*z2-2696721561113751625037917428263075540255538897108934838679661584820676494718339650406787030905493376229938870510551577143047124958554855570941024037475890440806830671913674510964*z5-113921780300759561330270113294127585859189891463007231048605852976625960627962604525630027224602145827604397031843239578554970270287462753889196894259603290226017042839073848640820*z6+649726698505001900461921900214931105503134103792375069295202637385520093649425469933594666161206453986845341496697692897204154020822372679187890912163692884560319750699590113225496*z9+96578625200849554521342628489901176085546173316623302146293354684213398769330225872853189310129460319516163630549227197808071603326155889565339399525234718344726922899992876887544145*z10+1108229327326884805422947357330015728896400053994855449749344647470360814726555594826557447048512720870376641802802278288937663533343876290696442891072261519055657650869574313753309, 1074249115153240260414574375972676802558875366925135000328921259463156552705972629279354992653650209910810181527654400*z1*z2*z9+32521181431532391528778630584871401273497329352912617232802378408137400827034214518537952229186839317015342905591369275875*z4*z5*z10-4034069551004041038665506522501031877066429586841123482563496977808603654416907529535682391675334655968109033244103472800*z1*z6*z10-4820205695865288578613796765373654962598695798977899815704601577959818263568835592334910661620750581955556830116081992100*z3*z6*z10+26513312593410804138864457700587258929476701232942497540420549364164706316887631539465515826878079308099759942847048961750*z4*z6*z10+99613627513226390048770760327245319228378940458128890813218618682419906876747853985099014162274391785585282283357296080000*z1*z9*z10-317863988560893494854968824929417713290107917338444360011475214921245011922933131464951800293970385540018198142809554490000*z3*z9*z10+219741480849457677258502486182934946822101362619790618508095481776678547701921121478058729779745769402083923427970428370000*z4*z9*z10+3683023512772499229083076739171578814322298184587496205440502624975473784420632616140711325352180505389291390497090334609375*z1*z10^2-8675873006809478389551357440616538315399608799620751914361852915260333194662927709944484365126753330875228043316164804687500*z3*z10^2-18279315886124581359577847786209411979451103485352914955815546570578775691649004062919445590724110004687704516142380938124375*z4*z10^2-81609740187367765345154289974201944936061678847094541846175353055927812081214259405671424472460579875066159399408532600*z1*z2+310366694887768860994022290222084351686067382234085682244382867111935398411615182146824388480021831937998528185684805852*z2*z3-217464948731219298051171746717361790202851820123586583180560088615050593430025356827489044864886484602148850745419119076*z2*z4+64524866272959202341185358025109507467542694408885756393523367221159218469163832809971259310185722295706135075287656138*z1*z5+56863482255264518988165262903557989796740202751354943543017222015364753961290292463934987787973167636518387415199792088*z3*z5+22266896812028643135735792762463170415703784363405958406643779869639972158901990769356588074860570226150851375753817825*z4*z5+74830673166119156815848069786043142937391270017073826262152130076404643510240292469797185809106229637763966466735115638*z1*z6-133496916615461931654077215205288425751539369962365016914391715195168624821591686477569954911846998044007008840281025238*z3*z6+133765656888850927583128900867608872692446354081271638081921894210728857490176966204355996622409948800775545240343736438*z4*z6+336145082168776562032922637503451898918337946287457857768685551268553094376995051353334492034501008172861824316229132800*z1*z9-1320407191805525784307005797237910983567872165331964767211522864651254216335594333074633223891296081798240930173678514000*z3*z9+990917362066536397835592059453659236181926994730779397580715722843756704586746391592948351613831486488492227423638106000*z4*z9+55100116703792806680115325180870993865126497100108626987773508245334314658981105357906629732751759269487439746771492314950*z1*z10-157709716693281866683366509507550942302149394179889135606803071400867310053883846238962641006447028693522651427279989914100*z3*z10-48530924573746339336063606684932757442922357619384515478130162310412950901843033568984837166134962612908178139952985120950*z4*z10+139783263356337180059705742525596591922206908567049996983583411111604199039049984443977762817670145265844064808114253175*z1-162573492917970935142673854238943886938722329385809068565884555446460984009024687766262699163833139511203723213403198748*z3-199734078848499429709718447253793439764666870619803614959958132863913555423403971395604440209237006195856259026187913051*z4, -573730706082812752617112203829781437900368779675394387672247514904261471264280138280440878151153456846184873179654153858827459981930191119025579020743984613829761293299207359632211968*z6^3+36476126307402008302553547162182934424805802743786868099167524392689570668663276190421525880494208902401551375641568681256865955049564689640043284404238695153732385887238835015220551270931200*z5*z10^2+85778667532160262546201701783290096013961559400540574297773180180613818407957246772018126543709377479898796812764884490814811846599099994182125242770286173152438190589727477903572249883294050*z6*z10^2-1567338445802898023003509799566633694292843197225713420993607999715082543719109885985196065088634096510194016197739046959868164411813996427953416066900913073640628254717357668753700690642735000*z9*z10^2+593339140898850854137404627066283523678618035096271163017588514477875161088009624199838783388493167713526426352937575974773258840542021450100734930245188264131419694384140603904120506522334384375*z10^3+141540194334477051132847834511604422476391942935405679485147580045896327550501331765252091914104660621855568662315974235618618308673739293938970558579912889826189630495085255929344991568*z2^2+74625922229903305791131754273252711453396846845722664918625989036721357670363554814466671866020495352679299193433056188005019730821093103381478546659222547055655630338784928636722171046*z4^2+23057079522788044689254846090300609659970446461443713691135897444306044025532294993491569062342462675356509648143840166622037791468193519764819092836329436763121542128609613128029038904*z2*z5+73230898280349737909210175830303071140682551339492562587093640291343937644461506262715533197609344383023318329234255272333716997792751342123483693555886367883167423258245879955867313470*z5^2-128584078668833948586473298380036472156626914093692340293845671027099486486378600958621087813211483591884763619882149840570732888263159335344938316417810839256971658666695470522361156608*z2*z6-5668950484287142894870609429273139925991065393765302198631342221401774806472898323549155786081448303158224770290976628276204398645949669548377740081954275348436248720773725245182118176*z5*z6-11254887955164207617453154078816585175478409574046221973614381819064387611982393863227550609970436430477247954166942505961043603598169543731234385734169609698227426857622048394937844006*z6^2+106664845563189021859734932147876378813153665835480961990946232421548971767046670291529621754002363837229404536915272080125775829506948241838412718889532643325358962243392885115225508608*z2*z9+94206251905155800446390274785216988152975787047416135239832821087464753083318731992702998374715662979751382263171909583128182296801409697365607534680434099443717765410500703840657033600*z5*z9+191093464247502374145730156650801322890021294555911491304428445700263717095267927562874967472346185538021441510830067551727662480128477927777882239131620637330173644452185884012193913216*z6*z9+3104489598781266998134289800679082464719211210825113022662651712492265137163060164625017411285084543525981627605460402818847258786349202531051524679835966427455257554858783129600000*z9^2-1410432309225620427496196689459892619515075479420171281056325393648294499349901140740567277638187961944028894147168679855323238853866348721499573599244001283860919152626097480235598921436576*z2*z10+202391890672869895067836552169019746547109747233543360436706167310205321463183114978373280236897621360311985794576077848230391714510212787679368587543136789233919883026994021964883492499676*z5*z10+1191849267981480858519818172672652199950701680571732614011051110510187294975848285917923731965517736499258410273307250436106352855345144063166067893626685433863693414007358784919600461386712*z6*z10-13596757507670891932375130999190385838746156321651512617715651980777758038407099048309247136434241399881583462878108432398184834936238598873778869224597896061272614181278466525848636971614000*z9*z10+9257531533538694770003352274922098279495123911972369909043781305517457703210957192445091383666153925813074897509978101349933096824399759192634277893684281471310249073707684623466178058786384600*z10^2-6056320017983479625494956604680748834753443774644949533421267197052635757432409536523556921097136793798711032008277378697627638286044678535573637347119115699591892613309596258204646125312*z2+263744124358242853217947615967507997465196639342804475478277144066670682267673083629090712966388046443458173648541448593366466330229940364661873042645539933736965218498646900697015843780*z5+3437186185755697568297684256451226984226854617296265604976254989622090977236535318228564404147216271384244511152244017028211363782955249538665035307527827508307286119600175046477660993142*z6-29336896019261305639552710566195449020074310761918193116073491809275814254654021799271251808893426697709123906152536908014625378297619876930832206218342208820330952166146515889509856045592*z9+54270673738073964383684676683666725579612541990368919633960747454639028169319419272883915782427143572165040338941358336809365018967792787372409049489725305591393851140958984398444898812563367*z10+127560853380220542175562775556615452716131443873139860178463519951878584535663265566415310452721641972179267371898107631152907297782284548266559453822178057954347412076807102320926400072012, 717163382603515940771390254787226797375460974594242984590309393630326839080350172850551097688941821057731091474567692323534324977412738898781973775929980767287201616624009199540264960*z5*z6^2-49937606643322598234477242097420841648725447972436135737050598867834718189001324621074170130108813751001324256415613159666838454771354351034646130912365495030315785206360083043306875660345600*z5*z10^2-42321376464657826430398045665295352991427082789701252469817589748853568670581047700854691099365212825768672396837381787966674396232197999605603523816600629143896880885289251724540503929518350*z6*z10^2-917068153401068003923505782724617361199389230162816360505795613528973958189124258731853740209521957059312836433188999147498501859423764453880922600550315145629678565328746198758669970592615000*z9*z10^2+65313731028438327256392585187358432272038470607784441309033671063720512520870094572291196208493639641432724681243173560068994582422702795981223007879917623152652981315893955499691691849791859375*z10^3-273853569776509375586225539756152192703201562649743208702280855389835830451966660409009252585842100839706424934726280014993571792547283022593775409064198763591862066560685615494065665584*z2^2+70362567159152454647277814600528312039146889093325006712159477643010085938150662852099671884580515379334040174803148862707264571500449548044626025305094382798355389381926136992370995670*z4^2+157329756561011553831060521609909697579171473631047868802154026270628417074379534360364029121766522860144813267301269997966064786293230529240227994273846083980272474567713945082369576184*z2*z5+73858983242509133007109529411709016418761977643948995685987145845666238991819563106288715950764310677568712142331737041346361308832956317485074681455728854779393516796552214938631925550*z5^2-27876592648592199386551515568379006775362595654189237259759048529515139900700824469572799183980424161384518459092573227393964618692528929278345360791237402288139288488518358926876029952*z2*z6-78870253476448192745748636979622935385954200304901927489233876057333633148437924424201504199684750456833085590380862683772364382327545167694806255400069556312124229992701197799015303712*z5*z6-78092506308983242937354069671324974502498891775073696235098795665042509650853618452317117550459748455465183147400485389768659131488148330565270381067728396537460584044204042507987735638*z6^2-312938030088381260067632486060475837983608801043200357417713881667451709116208430374904423921592047134714290700372917422005305008634581565591268305491099258790180497434872852112491732224*z2*z9-284083900838739894317599496662461213697943165587142306380199920170046526416151911320419324308827248168977939274668490437973730296360498770566057079121671633815160922368991419094249704064*z5*z9-575093551135277296055982566900841872598586324169062836863370590381736756241050927724475421513491388791089842395808270408379878982109416838357259873497266052070726329092305573086145264256*z6*z9-9344583696927577468919118091087841045167182865000505360475754932379279530247584725574080082000266098118150135277348430986437543589654645227799431833353887741527395922086961889280000*z9^2+1112939735892449217928518384383311214610909933478094809886700860460233945886944788660121166106892479608502497541870842116956946586906632800667890227775073638319181939604250200147300436524384*z2*z10-342166559774468399744459863091812490412496534078544009207395002675749645900415031501620686596635988294632618101909710422686708130247882703266479048019637772397932701582333191274766853092932*z5*z10-701011272417936491700449257881433274766241840154046672837743654739660120045894427447238265138679390815336979728321258247501958252927469816194152609070390383914663728779178418927472476188008*z6*z10-9257454011367668629907108386963723529484613399142727314268162102222484434910178292608578282278857555209473028949982608780935410056070216208554020861266336515523924307697677528524017866650800*z9*z10+2268339234826752298945879329680878533446045845700318372600783081125934153028870544586105282663556503475212025071546788766740571975950486126315044594294222024070465398354496343821048898110071000*z10^2+4484052148428661901114528583576990291057893725842355793147663850594699751300754179197365611692645462519618470694946251645812917477615233427048131387819362275960656116258453100833060394240*z2-543899231135389687758328635005753151913002615921536916839361499501902838541386864618810182445319625974978533610740233699122767477292193446154923434752219427218045823999246955512011720732*z5-2134258444869288634230713177227883107713007948307973269086696109438798987528432913201814207625216672619359769125281384577675722406304587733779234422855508425457519433528646967036359961690*z6-23431316631588060639650810350099777462791473774239973663038322080324180528428169182294644921702137151592094050475473075299095261436929930037722879840777836527296258465225467975259400493272*z9+23533068677111686070934931550475693388059853807703472248216533481706645966391223055342397652788042633003246603236081609680840229730498734054492827084151728618777885504639119902534229221766495*z10+80936204373294298416488466485723194373980074249960798992005150974213628579831285127640074572809343823359622673532694443148068876778938260884335245280962275856855341008026593744152434682092, 43507089163706230546790262226893410503634452360467967513321311008257840384591891485813877202472833501387812351870003200*z4*z6^2+1698415349233947234331858783649842005757340722144559938086556458512868019846386121097067402334817293746110835300980534724075*z4*z5*z10+165323209217189081586832830076375196573384053056562119135050436361307048389764781663142361470861933943530879246541496527600*z1*z6*z10+224257204915254596964415969026156655088197428045898391327956506005840155724038937519009273224554797820833254240703256879000*z3*z6*z10+1338529170267571931385133997761422638061650851027476319774039579990218333199614336836836036804353391702141693100910364670850*z4*z6*z10-937531169467662696400892725453015079402903364573163776405952874591955114844764170590279136064333138118355460156559931040000*z1*z9*z10-4257036131183417988901635035598769601321299589625694177992073761027508861449315044201978526367138044868560743734638377450400*z3*z9*z10+5244184236889631016566014385619184088182780405951986581195025096944231009131425164646206181549611779605420066880769440260000*z4*z9*z10+892425812991573601320165819631074645333814351277629866721390141992289649051544166589264601763206671664901950074787510985078125*z1*z10^2-1850217568888727059495386903427336675331404125566182100352360041132891394123811373079685918206053830965206004342656689761093750*z3*z10^2+1030910901307196506352166967976448163883913906639206117790360682193935854802906712142809352715317390752316192841159225450655625*z4*z10^2-5538240034521861303247351591723270325978119770828837183465571467686814284065538802828814041616026465127817203993957983000*z1*z2+11427747135056078815716502968726109701343360791251974469126579367074158418350574099777497447119415509315920774434020170644*z2*z3-5883942342600532478633660810767564979724543673634969588396570751215686384642031416818360042161329274236547144701535741372*z2*z4+3857627068289216677694751090692916620547467052602054636316599678236731118711887376663640712867263460889726967808043886236*z1*z5+3841591807558973419659459252483644480972630045267200589308503325902689241017930886276983297235810640106690861515672468786*z3*z5-28619538828561745193756375387448526573331852242860840384991129477204065623932837084784487975505533752173017319497211875*z4*z5+6961851564285052427363185943412501700865928874252284170968756425955666172044232033143776464874032333092009030863192146386*z1*z6-1100583115754089341114493617505494976112447553913176726288854799218988784670161528425070475592464075498882851860708147586*z3*z6+1709609842247864187986808627803465583743252225218498925568826788204608854056806287898836226290779174911177973523665076786*z4*z6-3500703251746822469593886785417238002162036617771891018841369406036923951781341730718644872404543606253991168593187308800*z1*z9-19904796016666964258162519563562350568280051320328043440273210605989495206385758661632798942442071175483321148586092042400*z3*z9+23626909287373268709827032678102308728750137677128297660865276563068740060536565771505327346960995303889318935880396042400*z4*z9+7212785358297946766862420169963238174211021005511305380513449684268682603332424593479001234896590746781496600752160226955850*z1*z10-15582267288072552634301604318155415290947727000922698128394108120968464945117791416765131187634561672176042100505484490682900*z3*z10+9981922021877095142925531277229838456452510706997596416888276198291696563855419527908217570813466433653371652246484954540950*z4*z10+11880236837157050062268987762999300962026653994716162920961711722368952906451456655564822539551847153291492336267657263725*z1-18769748171678532533662252491641804480863111164578069288982279846902040957067588903280798864362299050255518348664785219706*z3+12624408176014549532689299949723801228432355142028515581846679864446618841095470784817300655501986212982550256673267587353*z4, 339899134091454926146798923647604769559644159066155996197822742252014378004624152232920915644319011729592283998984400*z3*z6^2+3614261006790412324360187751079708524458805370602010838352090401351431757214889092793050647595210955859980111655668886100*z4*z5*z10-1233750776873476325881489273965248445762617804067744294085557249785382125389089827955119634257533238821914613489221849600*z1*z6*z10-1743283665662339299469939907779583022309004553625410496602699196256100384650262641938412820801271765757173582869155874000*z3*z6*z10+3786310230055532629210689790232863496915860118333752353626248533991757199203281647649978271866599232564111642852646271000*z4*z6*z10+45709619042776821100462679961512130285153414661483993807298972929886048261734091267109068574841740714093006799690495200000*z1*z9*z10-83481430147716639768920078829786167058707679951259875217833878245303664372618784361264530635581885534238751146494669029600*z3*z9*z10+38335897992134419880391220022403562046444618306204915394703891235415842434498817089127876170835580646816810905547388460000*z4*z9*z10-1399075224213348611291399729562047465753916824585167709574854894230623494839704668339908629318998615331236445416886457500000*z1*z10^2+2648009274179462240644533215138920857774839061374577864987106737482865273250488816848664814860941246718059391696138620859375*z3*z10^2-2123929847886049063194794854258928859130116298159263791290200682988776230136600927712671306628351410763080665194939403945000*z4*z10^2-9772729125455441969016700338411911955326571780899139412996633312579401071939266558957727294447570000599730308017103200*z1*z2+30557345048076122032053168949351472719799303117053074016644876215327133176669418358592568926593489358637148341076049008*z2*z3-19563250883169332162757559481444253277905388140770542786819031420741045003010458548233447815623356258457362120127842704*z2*z4+6615657323423558786197987437493104055633282652581361316452812539173088876495214558205201620669205291121765193864472752*z1*z5+6703520973136208076143197556936696914950203210473887114451500545881021750878084450146173830976964559518724579116249752*z3*z5+3436550236117715786970084244447339534727068036520246870549273657415594214864887036215730502066344751733879740393005900*z4*z5+2544170822057522672519549886299433896300579413123112962960755323484653302549849335256561776811150864430387785417942552*z1*z6-21819023837251022806934482811123932825766091443783928093346104428959231687562641120923681232268865486986025234331954552*z3*z6+21805039914002217230808031388096937633320633571876608548996037159433629112211440385470143713697698561390914081683273752*z4*z6+211692586477546536835162315586198463546115154090818622987973909661227249642841164413644077360333823745708714196966086400*z1*z9-383029789202535541887974914672981187716789186693337055171109602816711349012718279127057453361639199970673059124746828000*z3*z9+173854437157146648123498494837735977574392327909275499293783864890584023599973476687930743976036731707201406680404805600*z4*z9-4644369917562308811396456335984919991940034363698875073589184252568357880660412591451059159877801497470297024768114051600*z1*z10+23254994453853439775619927434920516735223434551760819625422810427893141479764311767334058451692014377638006483990605119150*z3*z10-16586545530037690554695090258456828476129770295716297423631573301900160906589717625169292780368576299630205339622803466800*z4*z10+9537729213446231976642614574882795803972371351914033933838592630050362263280710256591035565102701338867325479339304400*z1+95145753880683405591656820821848249276156014222710205611738320446943218257205130264770851763663450193868666153844959983*z3-79151173196258242546932353217981235825807292739368919495560011968842705698335473834272255717879663416562913207674732904*z4, -59763615216959661730949187898935566447955081216186915382525782802527236590029181070879258140745151754810924289547307693627860414784394908231831147994165063940600134718667433295022080*z2*z6^2-441185633693191332036062218087284463713389742977955679902059121455442253010928217839355514980000829600469373957365962956175332361693861034247740278792625609276983201157601349527698614527200*z5*z10^2+41696201156359433720355622217927064427944270495200796906984811378265161043141553930355896194726316806940803633435327319629862856115958567316381667121893073950206847087292097833585465346050*z6*z10^2-36651912539132316915516856532241204516198754346257137953807537005407968570109589961066026986550238804660314099415801371134002275260472551576944979431253610213854217417191871296003814052505000*z9*z10^2+8480073413385226125128391240610595906132340572708978189460213720721418476362300206098473318967877613764349932046946995366638615202869929068171224739553316998994092298669162295166168467510515625*z10^3-8426865914992618265569212925330718339506756144799921089580056530608627476106175194987812120311226922646862359808525211250813830272473866991156832067359971378121282992953092195352605168*z2^2+2419510438173438715776051582492502754333834991749449433484153009179953947327405410034086520689864442871215440721029229587552623591195636735690901238280244275858994937710821318976239690*z4^2+3011052651107613112451528894257879129772249523197136030890550710388854589371590216976102298607139110161027380505305501453981822046893756252990888726825300478908757430900873900059191448*z2*z5+2441313100758118360811204958488154665897194360640828279175918124385002828868909122726995135726460692210971680794271023685387849690853008367920312736918528107668034767029441541134989810*z5^2+1853764823928837985457570388003263554554475407575347375168553855285428847374416556952308962296489009469720521069389615671222351664797994255679045072939818156643132992172879079016239456*z2*z6-1486610240439288617345186257166242168353295305641541225847243920023809770700436320900049181037831909717910409626398928927117323250831583670630369448047549055139911669532946123879852704*z5*z6-2553712230175545297431003614876544648662649094530041085361315811911590049866563345731573504474283020504680439696732720140583556513358411419780637600183102737375258440531133915141471946*z6^2-4954198523705902112854347310948692048448958360385624836111892661726048999104281108320202631340452676187659238904332775076309592582248309211582684325176842585340006285726504928950021888*z2*z9-4607709577174661419748349820985382221289421787717038977025853514175972985398056958967981977584750901528905084946661892900221497140489240520556469541839585164002859298581444257608887168*z5*z9-9276983757052273763889324489108070394708336385727038480200469049550913554532477363327778863149877756593140360629409983534720495030535649992731358258964642570429368477003099019489254272*z6*z9-150771804823952067103982195880968449439262772736956852632499171265022692629893969691276253283644718156089390978650715326009053665988549245710624055519274982564876968818899599360000*z9^2+8878666608695476757205522807247117976999639105660645594489221677076943790020825142559692836373440413781259584834187371492521316020232518004422236833883303783981833829160476275776347264608*z2*z10-3426679615897358033154937033391748960756743545195001537809247754438237608543527997777626758639287081007177584348849408109686341640917406774026306424575356814770518015458887126505331771484*z5*z10-2364391930385650961202014772691985607466196217188538049870987013275854167051680836997205907226015858935788178699994189234138636943648292988572701633022679494043114471143658847168169953096*z6*z10-342803424623745127908988876328327806993699260019172794991731732574408466718956154143456043017421755691431683665488535050263620012939128001954407890114574659759147102518191422743109840139600*z9*z10+161090016084087615600425838444643536820996977520191261127216635075628659499684201012556608965614239240913738122556808525297080126988993282354616324876415537787106852461726611443321866624285750*z10^2+26796275404665351489124175610795410552710897794638755024344848382231433935210584518403523783252350459246875266285470029332030996610647834365993963312348790943262156923630275711281973120*z2-5774171598234915486624742039556541813514540334304960023472497357117100733497747551609008304076753218529783742750263679397193267461421901521202819505003083822834917763466962064533708124*z5-8184900838779155563375488409067239235500453172623631790400306642657755766699080774472247773833548967164918761403596205776398914880664411039726575450977274825783001154482494187351897770*z6-806070123357624734172915747988267761291529006789957263737593481309469405517031409620670405129587223011802027450434209973999481615279387308021836633418057974316151856000821979640711956264*z9+1172745166083158367691996735277049710894350507856151842981039364450031972380547951108223599633043867483858641723755269810304198642465677540117406680539443637249612947956977813296446011669365*z10+3313805099976214743123498929062409614984082055272526006863888876941413272030178993798111529751130956162857649471600336447446587359043484018893281491548631997991378239210898219281472318034, 43507089163706230546790262226893410503634452360467967513321311008257840384591891485813877202472833501387812351870003200*z1*z6^2+2738706994456773175419054164765115257098163989856597226145692037967874625884373731177162835664107448088439642417358016666375*z4*z5*z10+1713223095275040002922452579994204968841831309569317329316341420561224472424898684689211573286431575455367675890055940629200*z1*z6*z10+1053922915551051401725935142583278984283513815368839270418650985859231666403143510362277690482047953058427710267055335542200*z3*z6*z10+1142567023446683167555905527194339919052686075665277027985982449517961413814012692888580831194334191650260813962007913179850*z4*z6*z10-29564276451352027535087931792353328437650239500516938612547181362860046040635149606892221503555304177061967604605691124640000*z1*z9*z10+27245911664020884697912835925284744090903178244713134047634653022967554729857680621343960051224779978215965440395074406581600*z3*z9*z10+2271606091469116694845711272261789763840449534776591231064885701985116782794141998209805166924182708561125512565444962660000*z4*z9*z10+2379848601254743342715386836154795769317003085539441296554369692437629422860230943491241975784521789636429188602268707812890625*z1*z10^2-8141333337481956570519943671871076525821609761197595471803271758752849508530993412302146893632364094266244715994305468541718750*z3*z10^2+6864939991624899620038318249452409640009993975415640595171605646649678245188359038506681525634633846262907323295298170819348125*z4*z10^2-2707655833791224734706691707146331567999824889882582395257608829479834076524290963171740395647907233573255668611440875000*z1*z2+31914374853189683293392590386848804325898898558384357333786415764058887423381288203852889245523743632793584808891738470052*z2*z3-30378785183568039576573887110927209817200353524613387782087818252674398008635973707569417872632545902245424277198430724076*z2*z4+7278979758150907127986604956273579989230592609698562443598210737879838125790916523631037863030662760851467827905195389388*z1*z5+7665540787142059370086192504629656410451764020738448211207665243022106533486871524613763738930002854994275856444601552538*z3*z5-2586805239296949865832995229151989581151614000490813835489285917007287307268964823349971554225708245055539295209172807775*z4*z5+18392175789621087054494525448674720963365315387928130810263509532817470072726238521433379347948722303289935058842251653338*z1*z6-1034850244934542554579180868924118436150607372791704096471061633945676186125967829081638492691974391959402971927889697738*z3*z6+256462957187843349261324352824313886061270639650368595159052105218799209475706200652145245348694166828240999440751350138*z4*z6-132493275590212246030328104129110722139292239705076628609792199444537775624223784315924913337751820419878956220244156345600*z1*z9+122511266409612999922967147763591406916042067097353202213706045896664809230121366492810532198235551760135467365184014946400*z3*z9+9773301671785498078949383850240718194708726835319846582615586507736955441997810671120397889954953625944682713710954346400*z4*z9+12453550129621390202615076931043726157875117775513233544378166082021944102629427908512318536522260872769304664283197944974450*z1*z10-66508095317923388971419584774060205178817029071245964079384686288476214166214639418925308226077102027408182621246507062073700*z3*z10+63411779608968616490433401516765902996327228635960308719287806492746120169285142439568656015098987406080794753225141620817550*z4*z10-113914053309854450251717549788021048016898752004890028896848405452949583959287549115933912537993455964036884638955862975*z1-107956254275220483446507532883467740083381851455237569389240502799196816933386433029969576797716260086558173485082810885298*z3+128391959401793579283348942254143415610508031119213071271218557133146965347179459284378063445498742384282108899718924046349*z4, 2801419463294984143638243182762604677247894432008761658555896068868464215157617862697465225347428988506762076072530048138805956943018511323367085062226487372215631314937535935704160*z5^2*z6+329831499923789936552700209528880489897877047142811185303765958624743109456169097292984013710453471769432826847523028901163339862240524212403677860332196248727047452392801218360048913177050*z5*z10^2+544540428314037916865774685500781452897697903012625931993830471196065879066583412819869248260168354465195497027302422969503795841751624079956929618345451651131277747029995578399676753675550*z6*z10^2-2262819615521058439284135492270543205650117807929754451384832246373722305684993189698408262960425070931315209342020620126224486207314639403229061239927194489080377864506348323093405657967500*z9*z10^2+1831968940347927812367651090340671209646821195189100701664076858020900331045085625743448468589403839791657823166141796054718352904158811001706216243123883167789435019872340753330013518647062500*z10^3+98012060523905617658652597619274053937561984618363001307433033054354943764159560542212468088341676212540417067755763710093966406848457960538955658694209272678916973612887895898316512*z2^2-21175256873178037889078564470655002655935290025870135656634091281088565977349016128499057346221253764993933132819464510032034441507959875884187015802372047532185501863905633882539045*z4^2-376624825868386821184809093346907449466465847565852962855600861312859449955748939559003147490975695884280247855966243288316495323927410855107200727941642444173754645659199971332589592*z2*z5-39296375536120316989711209185544795003329555705369197607004729098162875569658667714120581250501288435592419225003557821134913387615879797377642081464601855330274061183464767525171505*z5^2+509679337943739682276190592579925451677456148613099551707810593266009499761072026412455290950576798034678791044790904492752164042737565773557416214133055798750224326426662649012189696*z2*z6+224123294843735259658487350323887768979463045312101980764419427675822353888369543773202234296354194949078248312879606249106995159355086506790857688887570613982526574324413403854358176*z5*z6+89039921219143824503592254166568347579879271878386143813525560553159304959234479773544161802995453145845139600273240688966442420438750449655356783659465177201582715210561371780540069*z6^2+1396782213612191058605927919116300930806014787054805166387416465703420312504857403856992455158553296343477118285393169029994245259830146085835906803422782904509000205273184800213378432*z2*z9+1388754893490200669954783138285702921683440125263893735970182642381840119221573197524917280536949794343436041499199363673579904071425637432177399956762627784636575780052213255594634432*z5*z9+2789373609526130997336253195660432603879917633260036392710313228278496379745261688620421182434568281109940336979096349361336903600865853091770860873465602683004878377927461442131813568*z6*z9+44755517378690781164821177893910388513354129198423122058680158166764484307072372161540203448260754124525608682746515673478458893709895333863497911459989648084231677185968496640000*z9^2-11701197388643051759841763714840093247616448209003454251092995963284534199142454585897052596994960108106041754528912977809867180595318862107524876385429998505005527616905641373200212753832*z2*z10+2136034449071570732647095708785244006257054622521227047368058109940098229028834677598343963082759506341875616554360923541108178199577194330848548506531618198707512821079186873708200144156*z5*z10+8389753332003319516857775595834745299287330789299883813681044090841964636691710277910025714645625752832758696294934168920584551846649681201976216470636325811105511737481608199820229996184*z6*z10-16966746450788532887667021097207983287763467659215848909517660551563897068933988596325499374274482469358398930518574306354301386616022437704097317238012132931455108182447919069036464904600*z9*z10+23245500560081733823405305183154788889826677162644988799869976435196833167143124438304370823844348970293857114558787750102605233400269469241732432183893434750187884488829733453167402399062250*z10^2-51695157900047245885466198263258490909618709961451106248966030674850736105263947327728596222975325715579978915127919028237331317520435194774805302481290472406207413635586134800661605000*z2+3237950398540290286846197131301379251975091275299196546794892301046609917830336105330274909964523029165726003728246834875545386610535408435318924314498760916727989291263383927926733306*z5+26200104712650185249965007920740064271953437466752684537818921157149652371972101837004743467609441796824509692767199618228530575196963678877203330371191438306583706438993858756746182090*z6-28793325929207822740805773708347745176276463187165962323296038004557697513642596754945877510961237312928190998974592131237878877107645289397573305739360345550108595363913941000620903244*z9+93361433563210819299850805474487394566576404136404865651994310156836336955829141544724829763056492511062101905908726817640372721085148478773962789204469505891768453710240648827533366250270*z10+113819449510729795612436670571525782223336901701129033027728597950684080416357513143274338503776403899354475563602375504277249266022579240352433855619165671564755068944374952112373780259, 32630316872779672910092696670170057877725839270350975634990983256193380288443918614360407901854625126040859263902502400*z4*z5*z6+8379354048688956451975419612655136149370986119597231281688559924773516497082845650070990408086654744659107271232511466328425*z4*z5*z10-4886069264365885261209450826730078154009181023465082209546669948539770270542208664770567193394528997277596358175675128038800*z1*z6*z10-3561107337869553711059905058071186434332966178845068097364184212714893307119264769071819194475835148951976660913466449705000*z3*z6*z10+9135478425356884332802518499153947961296183838330857986557379663746575285345045807651625755348592988762227250862119212689750*z4*z6*z10+91855608905984382705235814090848250141406068498137194990730253835618983375903674599964718847321882735485370612915616130400000*z1*z9*z10-120632400870830669317800428203290950223243658244648460526699557656476183308811476019348364153032544571834959368751157082240800*z3*z9*z10+29294322856735026675972675282202905651104927316413463429823275711379133676569718279545726192399842530753521339573152848180000*z4*z9*z10-6103991153128043698386259160904064120075115755685014150643281324139145021734242459062903889862986647966958561957906836618515625*z1*z10^2+10436603568946936101738722128024513283787957669672057595139815862145849865255838518851091123824365202654721987742796935068593750*z3*z10^2-13722412296464154728389131321135811662606164001586603849691691131140942416782979732380094964993430653335359325933057881924488125*z4*z10^2-10634526493531123994671847130505745728231934611519176861113005826465212923156057788032983504267483942485161798322627070600*z1*z2+55372960818158856488475840098810809969532920408629841153798378781629703572109428553193652423000795561438987369190262427804*z2*z3-38868948115824206870726405870815645814663964820930989848693488861122609689943665100060191587265409293903206085694816023252*z2*z4+15213736799416604696979106289438059040951761925483929520488785010072654801664331357561171710815417216357900965296459673076*z1*z5+11862341602039633671050522465480282526322979897849384056413712934770069761009804351041337289198440532548118420970580920326*z3*z5+9670046324661800315821054263802804519936120885820601291633819962962735768462700208243402950967665519434801576287061044975*z4*z5-11591357729253677956183273648632400727647179088669524764647073697668556598681595313425035173050652661603289843707752109274*z1*z6-43496710638208568354343260657831650609006643406576180113509616778297510919847938838043850871084618737062611350891207367926*z3*z6+56434739649245417639326039655297573285411046835227182394212393228047011126285795537767071964374910810451917820792804308326*z4*z6+416647423228774230110037292956950897165049650416156673599232689359589217110948362145292173054823599933891049267874785299200*z1*z9-548241791365110058258721539375333055075918595666116861194859275590595671411945724950972821745687842225926104811944571860000*z3*z9+133904111794971887648556622523911967566094544879040513380949332567833463695820745852099674634539969607999546641171468448800*z4*z9-28972446524828379021740595298215575039681981119984000036166291111240465983363785314534637541690814321850299454727023138526050*z1*z10+55930362938269705581106300544998673976949302201968685634894052108879123732802191106637436636574828480815043344481248955773700*z3*z10-88392285735941769425414627862912037136827112629607126072385989181562984005066973062128631713531692256060795603910977522061150*z4*z10+14092260572173457420644542224142701785595013553645409160762522569854782855872124100999477972341138014962420516124830915575*z1+133078002964316030812338812420926260260270089688326262395120323349385614241725435856609967262623561541314996251724855859354*z3-237579285312769686292852586266998376366059001388041114856941338644356334388508524281951952979627319239102479171945423140477*z4, 2039394804548729556880793541885628617357864954396935977186936453512086268027744913397525493865914070377553703993906400*z3*z5*z6+867877896168597323025874134443898073755408316942933006912650637171279154659218513250324770822461015176263809608265501340000*z4*z5*z10-406382439734824840211132746407144406442020972914901412849839433030687245492273307723952588604379381120133629094515101525200*z1*z6*z10-342625274244085669936116644304271177897822030039414349184383344635854756122715658891822476969239419205798047330735049360500*z3*z6*z10+911980890694515790721043153907781276817721894491972238614363595483947339474622474488449455825915482008329258591598511708600*z4*z6*z10+7569565297196053873469341130339450971146644357445377814351284649889627042072048343403853569809370961415695343001382295160000*z1*z9*z10-13104872271492392424968455165533372247396166686250601836873361776494565444289777294816337032064391196418239165496695869758200*z3*z9*z10+5605878044736694537839386140013366191050011283304999307200064349931996078362344377926842566371845722101389029525318874115000*z4*z9*z10-326107974751403811427091363348484606737994932370881201799583108731000371086296220454122449348979650470924769283051368952265625*z1*z10^2+416774591297930236865109222184687334010595141906894565551574584669568716239948193580010586051500256668489397200816789361171875*z3*z10^2-1201335270142751060773760720532832145313628087527250705746484775580734991431444802157478590704132205037264847075885930918326250*z4*z10^2-1578057071021438261682686035122208293152856295297697047004813001230341506773237401748816434479423054115002656697330987600*z1*z2+6571250036993351930404538627217786805830691205188375980588798268556965476839293252878916376904643457030420408578697041208*z2*z3-4353094642725159081974729393834626274009546325954694970242122440693962127197104222564296633237652537337417625870147905504*z2*z4+1575337107472311041458497729252775784599610454852092787543132230554087028650521092528853469747771649658061980974073557552*z1*z5+1187790779432731543885048319232459530297688312440617470749176797690863984452020609364943776267532472771403440388197807152*z3*z5+1042635758175278074330862343431155643631385495590554208996862450638320138688633171449359008218229739158069358609477924800*z4*z5-321606854174560628846834455568696370518337597375802235537482525193196445597822213927509280917374577371798709339192982648*z1*z6-4593581692457744269251317501139873982980563609281063751205390034870712502533753656839277186898189322898503388221444309752*z3*z6+5451575282972874377216224023531137429315840412297185205283990224675669171935379894602941494984439331624943875823131074952*z4*z6+34704202123550787760297360474611883929547543947958968396419692695655566790996908790752358082823859353602061742467465662400*z1*z9-59820615152573826337046400800656156205287253274419347332164176660048546325936637886537765835093963011772254763427599825400*z3*z9+25431366846033769800367969052234157735666737016420882941580311063846851004300850081021154182868404113303192704199734198200*z4*z9-800109963331758929193336201267292081761872457074557806755536832645819293112925707233648347238104794616982473867032035582950*z1*z10-400334608994962487596602684560700526739838391062410262152560328142384377582021953165068166361973810027546246385484569126950*z3*z10-6399376454522911498333622568385630529038753638048756994463264661988300219756677432459393231825027037793922479109519943988700*z4*z10+4400066714575318897708004092248168862028495309390924215414866800026489081286400777254185631266958491963765785986961036675*z1-37579539130811168409349712587775603892437419608178570632222162842324983725662652238700294893850036387030211582482730217*z3-16544631579048663337401739271106106673487722145050334104012180631944974246389655249303501985466303078492924470503613376754*z4, 3735225951059978858184324243683472902997192576011682211407861425157952286876823816929953633796571984675682768096706730851741275924024681764489446749635316496287508419916714580938880*z2*z5*z6-14974055875223691465406201480181477412248874335693436754462082786785234770157629762593971810715980281495334135627455312609243924969727476867895800798540670735442119078375015390053069754800*z5*z10^2-25620747069170203250227698735890456155036946116312208753982669413070742731595889673835876044617282571674809854688351480036498439348926158223884287286441800120208171618903683504188625702550*z6*z10^2+394341091062826677952688380427682112005433187288469741804966120999836518148494005102472437350349664648907372139384746186173962791377492621491823893728348358150595845888551994278815295505000*z9*z10^2-87015705137949143042188501469384365296960607202759354422400750954738770392945905690531497703021342284778335916656623216536987037840263040729401829014237624843806643185725697439484012769921875*z10^3-4589323298535701527324660956213994194988000999399500781009552026462483353323871727752706801059096392194894771499692794213998750520894148140543150025374853214821469920833147269914832*z2^2+3799406858772018553311465720124867779425219954050041110831997801309194984585693222822562176346950003559878151468750839069634010613165950035468522462999934429478001813290173039889890*z4^2+21674638920399742665796681262651314698898601825234386726960787645567840463130650139159014305214131289729857903302071001137766962005718906506812854774053825085119928486838848235087512*z2*z5+8263059388389222340101109872919701615306390846629076240816691110974922219290412697350515306673190901751809852803289052972012019367422486962958051450073128550208976655752711269512650*z5^2-27786189560327897841423800310722889730069176087437488008725891762928281200349460362528063693615634068285582463221403805512693835001408064426057042153317118209682420133234321789817856*z2*z6-11873458067264909110997024571492300539580497494540684134241744310050955161024938663355367541282111552805735566841941911041283819765523211759480944489409839480127538465948549051204256*z5*z6-3355593545238431657241411980329650750398166531056282990938180268311996388526314430487977382554280289630639710351763417411775103862964342867890140829728071563583311582884632104810594*z6^2-51997318599140453499549807450525121329560163117379997608355297010630615850301934670484232430094045940288345262584061723934344245519512660847736092186443961904755899302777419629710592*z2*z9-38318729657579409798336819193601993905312156298108563587248632537643342929442807170514900110713697575220373250929870084978428073137176650854675717564160165013035311871387779468583552*z5*z9-79533336913183863418727640605412657679614654580122096957574553208013383724046616107548792500962000575534433148684985676342733991430643879554866351318379512245461461897964518872486528*z6*z9-1323123358748642668175510125606349668077507673341924742327867953832551547631721374893146333768267020157353118826217084860969386449830000396969474164326705645465445572758487040000*z9^2+504427444384977486821475236286389650905147706088770870407055294576572073769314961348486009378711232447634248392643893895997070120197264580139912874193346871442102430426958099233025792832*z2*z10-85710081345999757095018745294509946952875456045938604736590815562091981040212151134025645690169480144908276042411827046685700902796934955623869500775607566700912361994840135823791655996*z5*z10-378089566539122568260504527370471210078210366707046305523095092170885459854678565371260983101727440335169259903843096925956853911227416415988493058285820681134412888142230125489654537184*z6*z10+3230657259222964967407343050170571229583329767882188023377927851555821535309843275955023704397718662479974267541432250083989135647009452866603219299993236232280141104689288423985095035600*z9*z10-1043613487365201078317792217380359781750280154010163916157880615673417874751162904376628667795274264770362742079887372028725353557486032779991286304920995998928478745419814127537757073189000*z10^2+2218313278627495769869203917235503288999762475522334580571469838531778749318546418175253736909953201173620006283040500882675465791708568217317057524120266750533456572319906235382996000*z2-90204031556612445720610298367524320558307502383869533983507256972820017402472088946095162187775203000524950833815444019558508791401599893307627526065028533127381567014031595099554516*z5-1160969177415537964278567333409795325954448808280975854178057494274896916296404036214395751306676871879126525758632844357509407481481660823520819121265141816011425429629560354544651450*z6+6511709035057074358187179042145889483189658890826395970283546857416734920003331270734689330949643323975775189019206532201796265348673413592973015316194719506857496379982491319466336744*z9-3624949691310997563831448924467969498388983760066198501912029181002091622532200294215837000761669005725046831599524181700624678203971072707299343837555034818793964484525688524499320955555*z10-2401031620569208948505509252551559336521033708114621602916034217399129146800961093954132917039323321012287960027608303217133716450394649615789314757135727825973507056478945931564159404, 32630316872779672910092696670170057877725839270350975634990983256193380288443918614360407901854625126040859263902502400*z1*z5*z6+10757539014971835612329083971557099056618379604294098159150313280745380648476171985352539797107070611694218997582707496441075*z4*z5*z10-4371670950869571600552137674257480957130021209560485797865899537373598100301422682635272302872162876297621756982821121470000*z1*z6*z10-3214376522777553697238968787221266580026938923944321710403136011793352835085649989516625527684248597912357000200098707341400*z3*z6*z10+10668834039686986997997994808047670977404651488818576828060329396241695185307860709717940209779036051911486081847038512671250*z4*z6*z10+82417705443092806830964750267507222612038512422693923960984970919836691901224533505629715392249671070495333321046336032800000*z1*z9*z10-128569491072772654580315429914300270610463994425483979486187384762276313565147384619395562997742709066477504922386879763880800*z3*z9*z10+46823806107859299957973396753324636869730120040963653524703601867078046680414239794139907180971859079683223337976754460380000*z4*z9*z10-4158527110414333879970829882049260150243670626130196017206583202733271078345078312676806058439002105597340810829606690864921875*z1*z10^2+3990846625315245831884008014748977715571059211437311035818680036571314402506603943785787370507370058464284987349246253352031250*z3*z10^2-10791331214065832004990423592207533865880163675079044989844691118571671482833009458100772987557548067370738801231117087889679375*z4*z10^2-15847449673532228190458017515573711477922772515540195700237439397449679927726280527061221839382825132350299755737288960600*z1*z2+84254452526139941659525639478250654656956507005095272884687740678431828393693104708190349266479688322487409839539180709748*z2*z3-62528723560491685285723474115420165252949804537269069919805004422848050430303390986355995910800223897278649992189522773724*z2*z4+20423322745365867206052181008158866349440251605924729934863437160493509327570368666479894602013570665396308037307567185212*z1*z5+16844225875134976173429046327298725700379312135471800567865959694711866630355773719609019623097688020440714320558596968162*z3*z5+10016618404926715811850261229223643159484681208322478772249360575401176285594855942860203091804634631879182645375942666325*z4*z5-379818747347262301869333239887012456612989533171211338685312774348069016020753922031390363218377832191325160525865514238*z1*z6-50225106720818413581331089386502396299765879605145464799868952265040778167505823333706638245348216874899386768780263813362*z3*z6+62601224255903938311081248707544550028737893899517463683790613214255516232641151675266068129744878869096310614985428864962*z4*z6+376611976264678867677196714737807268356445616264698245571118759274155273033536407267762410989414582464795878181775665004800*z1*z9-586557317988062977357764939986640551537630724031120627457207959002268305580784266355591838704582120441618112483570984021600*z3*z9+212944528582616469784180554580060877371208379538024984314960085644252625497846297953596721773123301074825412870256535816800*z4*z9-14326895032233603215041306918355409427060135923163651158366691858978223940257360926928662984842429435991028513544267875313750*z1*z10-6135096121115512275427026065032337485503461544422973942458674538732534084196302942547935431353607517624231023726027093115700*z3*z10-52034475103411245722157897847280073538591428538894769648831736807751411252601721285051882570108437249769033605429139404123850*z4*z10+34688087446429473079331418098070091687938953220563636376251689354740199641996671756684175065859361507026860561939251387725*z1+13800382719716837955351827729217132540803153956135522336982124061789102704213790273045352198284052459972562596959809765598*z3-157620499955725561655572099445868766358440700251812470988223425652385934595961431060421082589611065423285181597462715133999*z4, -2868653530414063763085561019148907189501843898376971938361237574521307356321400691402204390755767284230924365898270769294137299909650955595127895103719923069148806466496036798161059840*z4^2*z6+482685726379252695919568081634380158353832120864388437032447750062472011388186596323409185444909776789421345332731086546505992686818257371886743575094924424161126860313839326468432167062265600*z5*z10^2+865702246525027331480512988037134374373538660699781056969862622930744485336732651910109081747538360813135007901837512143975554836942553653787779936448739861417771621376170851550464499506479850*z6*z10^2-9130526657069900258346507209482851014977483326047848194195473693286855922882303464956813285008578866460043441398413097600213359824894389318365760862700341813023960199879014534938015618528235000*z9*z10^2+4371844584738250630285055833548164734840383625935306109756376793988750806708324894760153883559453551095000600408286274618285165736735948287802106690182072971568224207557099566362155302666159921875*z10^3+781247668814890978119621675162579006697125408014741253564927256674224045140554157576305086255542627177491514692012292574380795249038195518139848985603554828618757881457952902630790858384*z2^2+347726882925487901477910441965360316844224654999184948682940687565396326372690893127563522646937893692227016198949950629898670655965945448186369169838854596297739470158336275116018612030*z4^2-201052422328990396312410785691068899543184799952545060152958236357187206848128921506039261553431465053030580697036035990160871047601129036535902493267370343756100072444325215710885626344*z2*z5+324880735995524679192322417448230699697905743294538523817598424920721334226913148327091869251615276693642558649192335813011585624129222105653083233861996086370642141328346905426713473590*z5^2-217768801155082531565820992321895997260801699071156586127917608961013957750747794957820530989690695611705664293483236926013611617097500928475695241714875043375366010387003338985080480768*z2*z6+161485754077704612227759459679980264869739410805297165089081367871250257488286883291108894945109172275757463494307547767457777529023802654392189404700328826122396919398400437154774749792*z5*z6+26018781195371817095880955761778275594492359941954622838810888639471126488663072834305418617895900022221206025685317409269487190442982571421972065734159908276360604388326321328374907458*z6^2+1722774968649108556115352337077618506350576410802096741815479228626947725769531680214494658365595197862380560220350957158883780828587050255116899594389856096366989952367723168497660999424*z2*z9+1689518280674290136409747003462546294175012173070759380020996027956984773500489833640163541358496193241225868727471047303640438391181745202289327744979081562085445281714085514686047874944*z5*z9+3395042842054234597066421859734569876622501579429051275627529445792185044591397902972032740374975887470992479203393902438498599418167591388134824808605586910681745845396743977086718214016*z6*z9+54547754521888418571698609793713919090404132749815350927111489464799035446080154336493665636437553152381078952115753229026357496429978324166728603136093573882941860532415925370880000*z9^2-17213098677198469026260200756844655807636104939916415208205105374252743606963219022447262452199229484998995580694635266559783613392348424725265635278793013699277827082588732803524177621558304*z2*z10+3032697808200187884955401580479133900398159244205463242550814199995941271604433488990953405569862310126691008673428569577230388428316012781361945839202060260061868612234724990230948311592012*z5*z10+12634864557037402305017782821792713714946894381432185830190234924459557293989026472643746511043798965583207687485878748215586512758314587705284246446436399140629336189134299585577596711605048*z6*z10-77234951421756585037708605454890650075986754863409770795295374117593828044316485529581888760573934530726231030762254465297139561625102897479913484810495450602480812990097789413070790481673200*z9*z10+63811606656450326518952667498518861800595229262511634278590365631926122702887502126652657677683913839815399426766975212189822559661234322401261478655614490796972193258631191229914670615510803000*z10^2-75222816961683754154503924051644450676170285719032462371623907366150863280796939588391719891686392812087450984596582425005664676435647902741674312565782475977992787321008074869117020670720*z2+4574752892649191761058646567146561491683950143766807855128141392740625230829282458078632925783401036784155491395987554564374306734124963907973357084575523173091957478383421425819643845332*z5+37319619370008860837649361636958437858114000018796281241658204234373914317236591562044927690471633057725736479257665240123888201732458435891875513369579783526685023311583167409917821770830*z6-160573836186432831478813231512839782063719930279014784688549820199452408375904234301218766750358484485715677049374673700017972724313161267361305402877821798556506295034716233577574038901368*z9+339045757424019336320456288620646309904852039162915715465503689848554224795945019549041258303910122818201582523943301107184009054818986355061417896391507185723765730096126904677202308619527235*z10+711746831889590960390580496682161483475964799382971837477840079296098966806468823635971388246150246790714070034373709964821311459159184428323159858275720434334618439691301732908153778189948, 43507089163706230546790262226893410503634452360467967513321311008257840384591891485813877202472833501387812351870003200*z2*z4*z6+3091874202608063103787320983092713750962683710269180984611791665709088355951082795953435342312045169449440855138858580269575*z4*z5*z10-791863706622755298130552913351512377319090378010095522644372859120910608113587281165745489444182737095541962715353500460400*z1*z6*z10-984618551272589546231208020813613321536786396661814855103240768560468209911364129702012281775284761044995141884877342204400*z3*z6*z10+2992750965935441458284167432947262231644796828352040585848615231614383549036225156597423537008042294025638377683946709483450*z4*z6*z10+15921445840386520341898443040900347670083199622087705289699128649183237803288513995845283391703070553841734076315970725120000*z1*z9*z10-48500798874446435791756452043581326339700579633136030146602389596974941716235203706673198387565210525116898986783671054171200*z3*z9*z10+32915143600026351197554529783938410036169659906453841825259837956046129582177227537158766981280240132625457212882149438760000*z4*z9*z10+576162665905407140902519519290573742958138386641778792442006975115546287377349601031000968753684200712169104944113865748515625*z1*z10^2-2223431666788615689167255136910053510603457597114025851281676792210633572732231010531472547418942593494474211873097005390468750*z3*z10^2-2579148658527878850970355137659578255299346960794309051892298406833435283679004266765936023462368483214364701573044534876931875*z4*z10^2-8071432651198603133134627046774647059518509215666592981829928898082668764590474349139506188348073684867670609224671950200*z1*z2+28725298717620007032722761361890743057764700946072654140417618007220940441367636777778796285152988899376102566383752815204*z2*z3-18394349898292555238174186676525752348167159730396664596476684729452187489735152188343680146218836326624757585335273851052*z2*z4+5736036737290132617764882456702523542545150883242775509856832066012413786215989008275264347277671979292935325755563265676*z1*z5+4303602840082904696150193568118189899455277163035675874090467428237022041776069776913555964584877713059254757217880984026*z3*z5+3585831228347857137667771923915015071416070909429372328346931654359325774345096540002792530328836419533569888800176944225*z4*z5+4416201255996236459197473536737009318729065842858701955884055294539701752320464907874013619485016694795094551968945851626*z1*z6-16369172222864599268275653266473232894754491350943655782166752643747027042176457362338497255413792090452477948811349067226*z3*z6+16641165344550827134512716703280476821059722940932416239520138794200639689007486084604068662772460007891560531298278496426*z4*z6+75489485772847479625615301149709610605555276798155150477132225553989317837550742904598707919812628210889501481193931673600*z1*z9-222746022678920257974506636913260018366740406747547210723143607124530817808412936883547871794507854525053018777182439950400*z3*z9+148755111944866529010173783449953917075644866050251972653502509424225146575923887178389708174416820741859757233097487067200*z4*z9+9283991110674353299691037848267421176062236036347786270668193422529117349625211036345543003124254642105446052356618756592850*z1*z10-33566575360924825317671948643972991440670413595557142832421752950032512868827184597993350218604681778120235807435153667903100*z3*z10-5553252100791409221483544308173857017734128045081150321964425428731739024538247522578855156282392724773625948877095635884250*z4*z10+30321130401672788224388409251376568821949849746290748216141097797536898438381525165397313113325361559982617551073648901625*z1-66610575725505969844444023215123607151283019049253668118311071881238142857584044160662004279266405253896573351950797372746*z3-14172760894359640544386670448300951019115628688741001351953053010753300140877706854131815352319888477983622411147468186027*z4, 717163382603515940771390254787226797375460974594242984590309393630326839080350172850551097688941821057731091474567692323534324977412738898781973775929980767287201616624009199540264960*z1*z4*z6-752893783573663121823920772164454988145044225733820693262024122456470796401303742043311313546017665236046820512913354211745474936793010647181221816539271244676234152736931780810301618378769100*z5*z10^2-1042548113951972012224263166128713217038057868985533415178289067651943786527158364630684413674932059851983171005710205725846099115436101391000212235987346975161680637695594567247931206317899475*z6*z10^2-768625126675734293844583111688764013343104806527298628446782574024171370765001489156551742266023046058712762197262449791061804406833586572442370290930703436374358068431192289533984561731652500*z9*z10^2-3262576161054013692343346316478541689559538944028425467264833977752108516837619386404712962461250155847829624202930536314218747563267396251563825506013954920015940759459693570506790485303712859375*z10^3-550792866018388072843907365670188766303136842911393780862887811774022877000023941835639264900518857073252247682232559729974342040696987804507182581248846894026570695920900723661125315904*z2^2-2868653530414063763085561019148907189501843898376971938361237574521307356321400691402204390755767284230924365898270769294137299909650955595127895103719923069148806466496036798161059840*z1*z4+132158596205547672350587322005080643496171055292483574748672805393152376211044843755817308965677224327622329220075197863588862370525532185891493520637117549455751314046864495791966519650*z4^2+1333051291784091490700538415207084459289314461361580433416368593974381480921613150324513638111979598101461323460349613795164547526550044370013756033489659357115777357464111786158406419564*z2*z5+156635163223387579078492411333812509885513815617334244869359401864877568379965825523050690123752085593577895457149644109949839592410561843059680592965669722939189921482729782177421741450*z5^2-1584473409048313097060135685671617614349225351236559809583692726218221314238544341935029288754834892189732269847421433182509049145996825074871599517059266512847158207936275747553688928512*z2*z6-697435573234718897647446275099120588303192865092137797291833218714281911297132026159677171620675639647574507520846052071035556479688382239774151806112402834202476949190753790086132145872*z5*z6-279886345505001474621197019311269598450445287539607701278933849018139614156407405488364525589903838133712666165198617557024339741609395383828733256817467616278516262380203095132566834338*z6^2-3674245729592629737397424669480758040194151311189494835659757082853938374458404075642854942457271594980324101092912691888210952705652007123600479689157295017980376012626060736326697556864*z2*z9-3358655540123565373126328068971748528056603327229822181291373325372803829529123885512745075807547098494828761114082135129693132521170876880286131467972546505416340834916766816045374762944*z5*z9-6818028224351229471756735252394121651950073401539452536932635490271697405477800696255533275838394082890654034941219197161063230419678675024047358793870598616946149462699075898164706088896*z6*z9-110347047780151350170144748338458095323975037480351092516034005452991001868670173551435286797102052837467004825724692297103314172693710757958449620559825615801428871614294020218880000*z9^2+18622666771387855335549361069737936796939568206175785153319253711180452555564946805516107572941642799004028714696467491346682335550172407406837751168848893172596966312860162507978196817708984*z2*z10-5002481115807153200197216655384008231752310915929287368997502284970607995517836436190766766617036878818413229840889542065805951667244196522547558511298906058901333368712858769060571419958192*z5*z10-14691683187884852776902970892394653335980715791931078458160654889228076711272206142675144705835299838273603617810647314150746489165623964535461713022684277484106731389627750784209229701673958*z6*z10-19105683325229262683398526972895306654642010591487965381088378887107552350907565443687761377900818837277211165541453625414687753461624865624543829504808196690173324428138327446449989374981800*z9*z10-40096891839013315410025529853265225756433454910238852045827445319466665653737754070231537593163786068486287423378494720597214466622713530805537229816343305688472505090026597231991973296971481000*z10^2+81005959154584437911195817966502936019597968180780718925414775011699111880094265637202471828243441379594248229872137624639954812362472958365750176890543516909912178125843096930011058924440*z2-8133638148005751108379649737885024342627884044464028059562759659110032755324147823560995914912066719302060454791607001945966384158352647844885054781349109168461646643245515903161634471132*z5-43378800683870049993063924875222232448324898078846813957656598703403367739114303298410213371685372118807659288152085114370634492621509873951604189497981503977129604559090756934431322800775*z6-74472152061711595032637016688376721850496398711681000609429928699998454058118385468649443757058576033771840678804781505492311152232466966196576562691947780755109341698120270012823085967572*z9-146514885316758855670800515157725433968713633873092632410582632945122042902691672940365627989579636731880123330292007144787673923087095235663191469319514324656723969355502225250909117949133295*z10-121572385146809439558858331635497510652665077863210877318399435839595110772819820428500866194696954955869143491258492066746480275025998581707113499265269694598492689029956785619149595216388, 84974783522863731536699730911901192389911039766538999049455685563003594501156038058230228911079752932398070999746100*z2*z3*z6+523291659823331618265649171708416308084936816557624702945217452515878613066289139724482352659793827216513829670014536175*z4*z5*z10-147199922360675519826169157103076832085720150991924334648381416531618298464825278402011945610080168900951386096252005600*z1*z6*z10-195276937621435523923074867735426867823139211034281150713472775058032474081904105122051404723911326142769071938285743600*z3*z6*z10+526450734383887809369239852278984801065416353792880334411816361861092715882298551517507505694416285647684540197416152550*z4*z6*z10+5870137354172733727300984160064947551908210572588540924972003041024915161933218380914851798637163635568057648509070980000*z1*z9*z10-10217808204816837808230921968272887619596817209478147937630256644611995367349998257617324720697624812928516442676342131800*z3*z9*z10+4401665931034359288277168595094688382682471440483429725637725653093747203649524677517441745133871399977379949620310615000*z4*z9*z10-117536178502711048047857577359235350136371002997467579727461342798112786804374239840673243126188219386946446034276437109375*z1*z10^2+361763609257594197903196733910079717285194916818356629298184149521194981940189837889600392024376613982831176975821643984375*z3*z10^2-355938803997981221204426739900705266666167589327552464089085472078747508625707009360805156739212851968143754608526465930625*z4*z10^2-1259307651919584838762447913434000684774906790875173546848563962746715889027048268314570371362053185346795988462803800*z1*z2+4751444878055981729167585293757167802412811906002120612235919870778144923653362829458915244006453580676866261084244816*z2*z3-2944961550659804634191285753766454497086701799125250203784283871070396581828247646356283241472455208675396944502020708*z2*z4+1050709310205308588471242406801729288374487067021030040643082406201845043007310825199349553446813317243687738288889654*z1*z5+882414521097618368250872866461331672005869702119960712846063692999260763530952954614776501137908895050858334520439479*z3*z5+479234732979778922531485287477150895869044773241518033570448539665800569588932793466933943770909107528881290911597725*z4*z5+624494059735200777082189011160330162033299952680880326739362168051654408416414022320693920722693569401445218312528454*z1*z6-2911091939673075075752504531478708548930843645143143621279966593491463158127828246419045867543394468210321240440313054*z3*z6+2861135136005361629349178209049044387920169806201686054332550282052165577350338913550883064516729111933595923210790854*z4*z6+26921596403364641286610940284218144493594282520193829006680157487618197053346553642009595550927028471245749885084218400*z1*z9-46599495842297191621002830615935587019781615276631692324732553121219927690986887938044953942054660564690122908692172600*z3*z9+19918859271136527030549646076348935853630307048468895922124753860826296274637930070676703666470100894182973725168415800*z4*z9-89082757056711378719968104776836561986154039667452895617602746459361046780977091724091696822085213946048150665632260100*z1*z10+4192653139328359958948058724991392803008028977996229893248422795101494086845929163720834182614269638011009994597121687100*z3*z10-3820505192447568726832871966805739899443222113025456675178471547730829296112184500294878560914606324856003082261820738750*z4*z10+2147328163136599667169748988181405593421599809044695227290336091697081201930287058198051675202886248578057737424152875*z1+17883359807870006025174338147193480937021789852813653974780871572529881700777330895372657822713495595786927569661336841*z3-16615659594190892680718682143404054879427586939098635591345931531339511791773504337741589388972511954095552584469130833*z4, 2801419463294984143638243182762604677247894432008761658555896068868464215157617862697465225347428988506762076072530048138805956943018511323367085062226487372215631314937535935704160*z1*z3*z6-513463620569729081600977298802848527306463092101936123286627618663453846991884700091615985310598454561018921351483790077549189136008782627627442437715864240400193054708078573262212117657450*z5*z10^2-1021798381130668558743560015935562325395291201114939819206317007681751068365919003551541825332848147048059722102787159811654208078908039373696323372219238936383652741530650345254355988368200*z6*z10^2-4754272778739295614218378963616585695606278105594033472055789935051547244500622799883241995722004798921486191038673575490330198526563323663046291854965961285722171831095261887893322666192500*z9*z10^2-2560652295745899355780597608050198526664823437151889662696815774166394265828551765266710716875216266347259315098716587126078349802762797724926285437863527114331413719811207574412861099193765625*z10^3-375698365716645597618821408991956501742384719548298649796209985121306461311305956285144365616154620668360426623474725070508693549515203853307808255872478639958921134218196820519997008*z2^2-11205677853179936574552972731050418708991577728035046634223584275473856860630471450789860901389715954027048304290120192555223827772074045293468340248905949488862525259750143742816640*z1*z3+510035105070834891508708479218387181871769921118031090500458845038303840022202263796597791902201042858747722282684081620594097796370869693204085476240206259440803245496875858848524675*z4^2+1286602704739756795656817354701647744596309967018816298063235784789193282934772324735058642621172186600398800460237557426110767317809438280889740565702605304336495276572790421883837248*z2*z5+540835735365289287615319461715894533043144605635848204411915617224291323888377591861102114791950662096811990457049609067216539330295886276050923893135731747272121689049262094526337255*z5^2-1702855135706274468644829022134093058100569067475163092866857723046658796824599982946259959990119525724090049528751198800064332871151670119632048748465573124380787337230291743100409344*z2*z6-692992037854311632351126220121721720242752952913706480008893756306636441072074367714740560123960374558677756236146210304595892615700624159265341430840711282550143194174117025822180864*z5*z6-661786484935544158258780833317014516453267684247459335507962059998430285995824058565926205197252206605698056860750403737882902134232408653202209371738159025759841487630894818109144451*z6^2-4138448460723800680801026728253498620115898448363128735837874791112199294792698828086330785708841304775969041978618344244392873145054043601469936852988403764273532114446117658963365248*z2*z9-3718293273684585937090400545532306666967002394854924380227487901602917445798473588260704702233702719522619010661212592249257276134109806321396616603044318426739736949337344285599318208*z5*z9-7575279564136703901166917315452550129862015343965551347619479737160072450378579695541468746045508816720894580686299580981530670831929407314194689905241395754549878543788875367862343872*z6*z9-122735364373526799419343261162647219318384020325439474758645514485151098015407397742325029198835676309953691933490288248695832072397393319366217165465819891090189930223950684160000*z9^2+22222335205939989765878148293753010428467803998222740621752215204723235858122818769569739123653291456730422738579815112123801965695853792784096786453763420467818406268779984075809893595688*z2*z10-2817152657608610786404781984401269851194386366794062690284972485119770452924043542699877984670748933285135460957218336686255754842511039136788703784974678995197216996446985472668016003344*z5*z10-15854508369811432464237135137599028419471543944416847655157749974919942902694243471017956621687675119286365800905943061267522644490331169153528700486857853783204093072555449880755177650056*z6*z10-57059935961197824646872039344370608278229028284401870852111100568307505980502407856408110748026086713824096259611058630938227432579811234780989625238831998581885456872153982090943536042600*z9*z10-22039310628452797190309828454934055311588291782744700678249903174361095136857546046542425399052095056187556763365390322762233224780250107541614656531546425661380090162114639976841719995605750*z10^2+97399409821487309112697574480884146041307111224420311678854393644484679521254471421087077142870577995341475627426360772313743493746734528666256019128855533655521100837329706830980662440*z2-3185427405692631812095991473135042857287933563021593390938383038775665641228495810964842221563946727833384172617192020438559634927291161004115354900402776587738076780844451252475204534*z5-48607084724521923143056848341618118201855219102752416381735394970660250923668188173239993150387911645576421268225997143000932117690189646765355001512154717035433891624157867412442847520*z6-164963690877382603807754899977070091486522097634527032590529425270142874349303300995686702291101185389769054824878966403290621741069837937183834539393943180953218374755936813274768628404*z9+10861942725422564805444366649465031534951103044615662655890730216242914670522681160333218311212766502783743148229767557215005240741413761067609433406429556871427493003493256800770970619285*z10+366000137214340719225479053218765187372704294233481466830299956862291150010184771036690252812710131644799962272643447260437788193729104924684863232321882090991884843109071120517883601829, -4980301268079971810912432324911297203996256768015576281877148566877269715835765089239938178395429312900910357462275641135655034565366242352652595666180421995050011226555619441251840*z2^2*z6-6708134779896440816838954845054950604787705366387599645771448069745536619844746557649358821258104664462482256250058635520391759301572621867664008091966983675957833885942438638380460710800*z5*z10^2-7874096227534653838086930364595634781342783251982764964459516379910985467035324763862974469113719280700728714072635470113434910509129405779800537874965666242800296582120533251005056105550*z6*z10^2+2980930010030363324922611809541374676022494858661272863003014610297732547696276386318228595774771318456218071528384108115878683297461717928614298994284019236333867951555245010065296405000*z9*z10^2-27001866690124766682243530834915408214304388439460513748616633432919556322336208579788796365963763798653555267776858886339985220423689348661768991514931115895707595589101582914376236318234375*z10^3-3264201550510505784664764248352579650746844002848471978676991764277867286483111739025205477929239069750203450286828172164827339242853943541736095466284127736068940098447887747349392*z2^2+507541329347102071876544723866888921556031434393324671162040072811811611059808026174632525868597368483560445531357269454242416102258569134274099782474931032871805644013250103367770*z4^2+3375082689148775344119434401971660160341359169890663595259274169501675251379742384455495661116115725047970118187840878093303502580628733469036421552496140495150440416676711127555192*z2*z5+712928167229388161365983215519122359206107555706434355853739259841100341400321708642923970395030728873194807167079200564154183978527316565888752207472642765011073236569612341037890*z5^2-13922808356178532609812841662376374500825328040443066638992901534035542799287305353830506203627484545808518133223317259173888086691263338058663286601542951542213672952655349400231936*z2*z6-4542229135621238520263090136078915552636004359731097405509329842140291389220528297960469421252514967803870336065667265870638034997574195976639991046648783353411105532490820695806496*z5*z6+616185352219738385227130912967629308421523767701433160622077496530798607379883160885209549322749873636722789547959380258501369689809403693970088497337871483242966583345029848768806*z6^2-29971330071469842692844977608283914222158480900434860914548617206905055147392734466987610165586536218328442100654544893871155231848944642603123968532640803797124819450094178589516032*z2*z9-26882793880548523700300695018901999194748242367128270827839021792892683230578328080654307962396005439142839617686911746461908480620747107556860795099269646497486465444636622742600832*z5*z9-54640284894646996457665011075515388297375188700087304173943716280581261724082607702324195306387067287785441643616475280190000580125152744242693477636797431703867327438705041362365568*z6*z9-886731491063581133163628098861248499830360748301409354128331452586251670738510787816038691550815809352713394492523837036930682031822716083653527251208721282227885708707184640000*z9^2+135482911639239308077410087557249980847752109715298540487911100802256376542641896413842610068420449956542888416167832659897070139900415598262090105966580464629757017562633874948751357632*z2*z10-45434182939705389799366002215767148063948901818634489906956313753026321472204460219571367115646241006801997013320063873735924969855043569657416382056576973583032682387085085606063183756*z5*z10-108493963309279467373364106488130089948020518845913783029649628406639430292936751909329825452252395123411228514462386180827971916704305649129394871372438168485498528487520882293466726784*z6*z10-79769220138999834972960827821541700422555708127259899578194637280874476324010817788533271704627889407482320614207377332984409386476976711251198011552754826791753648456431931208178300400*z9*z10-349436287348432251266870118895512533215753593390696027294191916156136819506439450200977245109693827836142434177414672635934882552863159639419767913179816263162067980219512963779051340371000*z10^2+585948696364378182180946646493645253646437720623552400237813045893292120383658456208327051230987787626789412904056095159090244441485265835119541806005792076850530451131618881380894240*z2-73289785848744996722281877462589506980835028370978738935892777718047865105956168320948843293871127760714715005059617786119082073518516417537798691899885710419631945541879109967674916*z5-321084667983126415560206605444170598871990286384390732718703096661734816566353067593007103914388357735407297417570591342628627520265019884264981740368938662672839573205073434749302690*z6-451541000574034209363542009134215629767573205947718290556701539766548527887496818315393167825918913445736668103372449738829430428651507110842767512612317327976473816298553281573697656*z9-1430429465859054529331369964834110466467249834872993114033618910325259328595715997790623188422164171446830219465418008812336694614121985139502878094075978690529350535884739018378133888695*z10-1753240645797805741995194652139743635520189265035129674319344123663248915191274951216006402284333013491571311525793538350076519059452272792303080496498172876733714685539926935211687884, 4350708916370623054679026222689341050363445236046796751332131100825784038459189148581387720247283350138781235187000320*z1*z2*z6+199203522082206849325681993607674930795041318081785484986046725647699230249507490497161425929868913090593349062565727471165*z4*z5*z10-110654576823477813114051124622914597028738894103482217106497360812272711152642534185342350598843803653024742179139104417360*z1*z6*z10-121901530385545154264715384024418089935815157148443545708769903220052103773129033040339288202463231957702870994704588362780*z3*z6*z10+234287598882474842021540736739957559784559675379929109021294045397517963215659781878641256131218438734984338414208357988630*z4*z6*z10+2161681615488997680185493567749788528191130373270510616758480845242368145869649643410234269684199827033524017977672461488000*z1*z9*z10-4651388413656537498094072916567352917641875070655690648892535797185564505954793949359633011257537427858503161704070329607920*z3*z9*z10+2517906957225453489043253398131249173990644459933635673811175259169709872597090578903679434530177437833416894662728037238000*z4*z9*z10-48593859798206702853619518437780389740143209447170761055955934062006505435530615025889068171878954152839587729078919767078125*z1*z10^2+112646860609693327152538120366423349835560757267974305538231718523261705206707089069961522693510105719160149412584087635281250*z3*z10^2-412580361161389842100712414678078304746696214020000535718287371312286059247484422062376477746330626895511410294775017457305625*z4*z10^2-577124348273029570294494621789813960916352902587685997583153870116178782778035923865122566791169086866533257800986495720*z1*z2+1477187018458401481086987563514337190885035313038122667175783775987646534296326107777655040304753552161926310738387394412*z2*z3-685799996362164370494222319961041930432492682720107635706733236709677969848701769669485979400919007600422314887902961796*z2*z4+325027199969988538712167451323234328743862951584649839219184339693898398101128936845634843793033615755183393680656374308*z1*z5+194783542200239214261425216013444970809503008637299116960631123363602809187732873963379381897739197776054034305838587038*z3*z5+355229721593157609145476358940446371602772759204849450770030038514932037660496627310965302423905411343255555613730123995*z4*z5-129900882644549782739550417646176155369103887870402372767318855196380180139891684706407810981386602675592424591237639002*z1*z6-1355450347513650400926502132222850901173699412259612343442590696648939808241438591049497187858594776094286953452941633878*z3*z6+1425144041533211800852207711415216848058893834066317944365085764553234587224440692491958349696494144302017412808219074278*z4*z6+10018634232415291340667870999900623989069393929008107632330433468484313110451806094846930858658774938728031399465101623680*z1*z9-21288107692494262713220292985269414933362402584546756129219012015871256175741385468569954561846780280347421915108973174640*z3*z9+11395326346963537425658056323194759836748520229161922954967034996310787107423392765320616399707738263395601911875356939120*z4*z9+145777987833469582102291015917972262325628251879595683698230637747792138744928883668828438278380333554231217803903881916190*z1*z10-146977082302511925255852801024682414431339451678708441921220076469942674043191471686867059077349468755397025010051246840000*z3*z10-2438931094489008325041970571612091448453623830147737180548148063340445663239365407487443608777454286891363602404367284280330*z4*z10+1972236232762699074192318172954583444442280698438819413594337445932377435731963659321540512304997489932638387466399991035*z1-372164600757756053295363566773358583476348991199659907264286179120147724178429652898273136810523350129125135084511348718*z3-5676724311414978312821090964570682284171711557742254778500262236280511367498710482432093006008719969154825576568887420341*z4, 11205677853179936574552972731050418708991577728035046634223584275473856860630471450789860901389715954027048304290120192555223827772074045293468340248905949488862525259750143742816640*z5^3-1061954832102754661497228483990614448815160110405871191448956750417452808602618029757833132460202297638617205934067953505137701612486388279167584174556991821342552273040183894875836030295400*z5*z10^2-1406572125229144302449528070401504984521865906779966061369356403740590513257065616799039558926623883228528402079099880065600626630116491200751315608001797160078508163974181486396114313262650*z6*z10^2+3301381675165734996252766428336809436827924997260077764465321219732542357061696981748268647856823847680564715138021797254034230053078893790208587987614512091487242488125155496580458114965000*z9*z10^2-2834477536722933089323572349327218705789374242684716389186203504894627147931020407477255529310300097219587142708605702987941993191274104501630129838950900215186648363667035021582760099562171875*z10^3+938566838359841398248681048671951226690232735179880375005649101692350911457972220501614903254997884634297093687892349609886710147752321529839475255222424797259922599720850770827599344*z2^2+603961858438703139090702639539859039215966078059453081546389868692899064681535218983809004343700784328015497225345532575373435839110741587512070489820095794620711154526013883433142530*z4^2+1495024267608761648937332439851083728690752154436349295840497188708364011607849185533120811471446288229692374247084618682976260662276012651194594779201919442281477769445244793403974056*z2*z5+652083033339883553195012802231420202924268191478446654633032887029172416962138774834123922020733661473546690320154464637285731024728645339495773141928903207780126529396087322446238730*z5^2-2000908226863638100420208464903468332926748076482958784658747544900945704082173521014935577828809610642557902441330121434695702869059462067421708633153794933917124936743979510187168768*z2*z6-833087886458809139610409664352798882946010893821464807145264870042074621647689672832828903920587818519919420079814288530899884453843873483088948347197630802386186768611532921598223328*z5*z6-803948203721589972334533497889192878812611675795974082942878009462693083108527466467833350642107641091589303713678310163242674987141923866229937710938621976561584475102491341123239042*z6^2-4050086881072616533546803001388855543434003973453869549578301412474201553472205887871907315503261049418534566476518553972213420343428501089767629184456785618713573419609864128513116416*z2*z9-4236653665157602160535096704520409908761973350890956430599022148247014704814467327835291688572632464863634179736615920939910398189753231682362586957174924942939526949750147890856398976*z5*z9-8463892571291100456644034693289150932493462305545785455300144740217142068813143045306806170763939553066343917799834638018809329648700299110101323934465848006597445658215303480336203904*z6*z9-135073874718530175969003013149432946917153373386595194111006771026265811895316187506606318327862661573390782424341551903622952870271260851046906990832863059417982849827461611520000*z9^2+34263547906851556619306584303127328099875565998359587586979752763281233215307659195083007409703609055364313389959552735492365023719950542041380191077311461715795933413829682489442081201856*z2*z10-6849139501307576487661151444215777399112820727908817850792620380083046247226388541334017822125766781629557675888877629819900742501896489260287806607240099242272992392846741963592377032588*z5*z10-22653086106956596039176128618244339313316469376369054105598393609653738745400567188234282818401058679083866960171482092177667863955494461175647790894173299646711599041675536539726398970872*z6*z10+22803063625191349721319088125647955034172475380681891958813643869054589777189174739481549406665361651269869471632877441870443536536596808472855524859036388600006417999437626609488350262800*z9*z10-26797320567719970135407195672390986868558070546773170392895380824865502723590559697869293601924596282786056374391765280544190051250497817192869180264678313697496605790809221723537778932486000*z10^2+158418246324358244720048563142703822556454892853328824862436039061319154218986096353430549625856125028611313811502607371111719753424831316286469810927217749089022062642424473390278464160*z2-9831913893702844398186491097105498267632879975638063050122541354465107515477611044666211356194910500049729014903770856890581932735108354148376888361610202651616240461716800829682415788*z5-74552204491035200564433560603197636842713427310672304198504771857142039338922695398058120532471067382293003047531540393287632422594048131111206151613937714909751586635072817075065803710*z6+30359109254060602559120034388361677085427982343131366915971879647203927022018896636053877936351138470410684237696475881852880576831078632663554600031439122698665468305125140911561577352*z9-1422774568306499378564647128808224436232350660782495206146999415112940437418470398861316847992198309713162064924028638102142598475879246362640787628691315368651530698445101282644849393795*z10+405166304365807388753889768377642756185265441395375617098105821161734310045934717200255799625932020658291607789791991082515687317150206870310413415205023993753584246245759616225807362028, 169949567045727463073399461823802384779822079533077998098911371126007189002312076116460457822159505864796141999492200*z4*z5^2+1550323246162510038506935579306468559321937557643416516258426988852815875972771358535405334682174196394648237174383599700*z4*z5*z10-775127564242303216205116366539398535083053151391633084811904537874665103322385458446529258916502736676042473948880678400*z1*z6*z10-875308872844687651057068429778495764381540732828666402081856524257477535620430055651847339118534703522101087701615406000*z3*z6*z10+1667477046094523362160196562020534069454507535037685081518989198513065399262727733433984434915203468235924325170481712600*z4*z6*z10+12212408117354405709515348343586522547520021163963694773552824012392867590142086609746490472508309669352961059861697760000*z1*z9*z10-35066401091212784617004799286297526864529847517723142671683161473906321144740345659199090472617740400190113810718277446400*z3*z9*z10+23093408876414991631420342351680002054555000427005665184249844121509307977951765400500569408631063036635945017948512960000*z4*z9*z10-669047418650069473609699116257779434521745755245162236631453386201365056521204551242692418324290103591429346827633535625000*z1*z10^2+223088135980549665152468423865705737615622026379807571754560189034528944254579467498914897021354600508210034996126182109375*z3*z10^2-1400170150206899070545450920906986201515310842889858682050916784614823359091893530080004629650308764331926880962677321710000*z4*z10^2-4195769554045275769422169631608280735541779084447878449355536733370651328305684310580144316302926715783172218817436000*z1*z2+9830187986397245327500070846802899490913257484935438741909402972753478316563609168828708627635175377291838563944016784*z2*z3-3775670952380073024233892612903569371032544844858763598933063746270093675674148887727752059671584984179184923563410192*z2*z4+2435123757388128512431626462054154494074050901815964368085360480541134272614463070488617018946266825000897798745783696*z1*z5+1265892566769555737603922460621025778097175226726262282141018861871759423620713842203081401289474944877783251290299696*z3*z5+3038914022568192138644161343175240884110702271515314060529067636574296476282542275385649851318893768583668373067197900*z4*z5-1003785806013427909121449556688932610408093455104893647686459309938229911912632334653682067203469952425777924973380904*z1*z6-9769840530423317172703384077710967190357987824424348232354885855514265428741929822232150048522938695286901193893162496*z3*z6+10296925151175500433944530140442770365560833628286426273596989631448455081505097086395036167203005350493539863495611096*z4*z6+57644766649598449563994089260571220614920441462543120660844428208577653265524389756143517301576784448723905007543443200*z1*z9-161013696281979140065394993802660593597998785504875027715959438981650264264641537754285280818418018367219060441219014400*z3*z9+104437422318317486201928743119479374189396755290195707224503859480274363236732779755326203181863546614252944643769638400*z4*z9-2083302401474532099309928517992954285085526118309401063018249336183363642515062653039771028240353953107308676430974826400*z1*z10-2930983026385188595850050835553172511997104064071296346005777953998833668836074251988179653328026105597620604806256617650*z3*z10+2181591965861019967577166339934721956807028633234082474553155253674901956085836225556135397100703533151892606701361416200*z4*z10+7326722073063855938611129989613445071956137580517135157542437183547708332857462539867536046226178226391486070283134600*z1+38997288680100817986758569231245547610409812148223956027029806533610610690564217126652151272483545477408943874608527559*z3-23562914879443011648688795870299494036216265464569714193044271162992756113221636164371675700741826765005544953334740592*z4, 339899134091454926146798923647604769559644159066155996197822742252014378004624152232920915644319011729592283998984400*z3*z5^2+5351868839060995686563159952261845909028796638328165902097726206302068046651341467329208307173684000457244065061035220100*z4*z5*z10-2106828954177006598247297131631989946373045326935125585614975885089975496023398142727464504117967847828174896568614361600*z1*z6*z10-2666416400271735484824258140604632163660716128356798500969452099246202306027616649397132171697295300199951659455753402000*z3*z6*z10+5754419201438634035617202655407371005849156958161611555317234355202086321827685659213776778996015477965553707834209379000*z4*z6*z10+60032281384831289723392568422786115640543853712917813235304408018174869927439791401165425609225369801761102813417340000000*z1*z9*z10-122903304074988065155926169075938203704711836487069879697583883396630308275824338115962120283037680602881762465140501893600*z3*z9*z10+63695304309465423684365793165712873947858807711017959138790788681756470849903927093833956217534216832653428477000016460000*z4*z9*z10-2301462439657068889191914034747028870972088968663420505515516421397658606938793618846409386662773526838521702056301900000000*z1*z10^2+6052889987130556091562653551311918842224300518389449380357179244380077580789378315072074698689179177911814833155541302109375*z3*z10^2-4415074343301817821419047277400195468141941121371112142650378509154837567995040925360755136690281611288308740550176012045000*z4*z10^2-14104422552929103359607284072931558323216873490732642658641266899356682006970290950402472946868066479135679326693983200*z1*z2+42502895251052381926986206695978990246895132799031806963187451270264327275784238937521701809688396485478542867866601648*z2*z3-25306664366952279064692246612996466371950786800382296479868054412067365700360146306304990494213205270879706506641459024*z2*z4+9526531150483940881675331264218831595078386097112799622066199992475517092005884180490069717063595763650926635321564912*z1*z5+8392336111097414407670414974194352438248873857316356050722931220277819483194865107482564780420277043183266764027722712*z3*z5+6403706345889943091590059735558486312685312344685356666991892437930406190219351193742616512933187672007044430867551900*z4*z5+1522041935498378996179864382616765531198821136648535493058012585293098109280571712689823080492245047318242838998902712*z1*z6-32539516873152745533752451431679725076582520141581218619831585065281086519692766123231916364550848997937458947822689912*z3*z6+33762596920071119201101895125548775317902033935074022262758355448739118318021213688263093000775340827732402576971881912*z4*z6+279028908936672880411436203645281303561169758756266876353683956293197382577180446108767333583884492331519201643920454400*z1*z9-563854676051075983719678675420585370628542890487058940138629325025177904493570577406479716473720544247024533926814444000*z3*z9+288504219252991204832439597907996134052956325215159026302770950643207086439355838089451094410897516722246172259520869600*z4*z9-8278110504802852569893567367021497951170174223321427712693716926483356262675141522929830764398418790197424395054086803600*z1*z10+74492195040995119866070173372305398985684035696678432286307854389682874287065158837231379830682306146032038030357150827150*z3*z10-39817251656619641565308753056711341988309441052793872829715798955747792423640485545615634340620109086440578794929856224800*z4*z10+14620432852842031356502977915749832366627988737824576596635373920862898613936416654567619082703963526382075363133660400*z1+352554277960848032443439249438097744474527576469147468058944421496277089640948383940502004469992247172468064161695212623*z3-238671948741024902106587130347792701574843540405583831799098563645265998999299815555065262839904034323713047095785769224*z4, 14940903804239915432737296974733891611988770304046728845631445700631809147507295267719814535186287938702731072386826923406965103696098727057957786998541265985150033679666858323755520*z2*z5^2+808590015604152771153110087503464766650070041726745608397731062209443292676900624496183846420672484090829195353502860042327096432295770049833984230730491326677173217245936984844430364124200*z5*z10^2+1357012550336971801751999684368612124265753900332767885211119068057050227860771490986027145910725500794316504518977366953972840626092470629089145545717006040507116482949997887127089560208950*z6*z10^2-4975671716100628170059174889378102221879940143058226514237215661069248796208694344788288814192204901243773693666565853497952839931308916911342890048324243900254163853865039073409852605645000*z9*z10^2+4581722030561426804403880625707964104485258336265843036839535169577735093396238716726068789269548343803697776148891388378416082271161617174168715468699925518182302096727428240115233107611171875*z10^3+240818418826284299484001735957109285209713945690326745315261215774776458357120684954030758352615732154689821040065292750459442599364003538531595329631656721214244964373421157234292528*z2^2-55168741153907845982071439396892809030407048509422703919531178759520110388323924607474194349456627675536110254610032764566769793628443316610539739904945560103882220658274234132445810*z4^2-917375068647711439999261492358896561817808862340922408713785165726766220303591755531223659253614433011657305972956404992393283790642264184791609929457640148398222342866670915686160248*z2*z5-86344426341645329801114190543860730112685867201251191614383262914928455665207459928326495059098161268081161983729488887543343284347212258956613366870785465439126608047665505207964730*z5^2+1252655568012458531880573903317239308998432462726099574364448773825357070485401536755518148468003873231635884417790819868163294672330904339879403299680486278651454018362157183272449024*z2*z6+552022620495122969736662614862644898976946181016389556056411551499402405985747521799343939279502476121941733783733986969090510212531885559709080220897264796316336493877906400718483744*z5*z6+240222700077923131584530683294856717953005628379040684356358631202615943855359952837326089346311628238877484204539305840765817964984125775597040990708441778752264350695690484151735026*z6^2+3547574295245299143907797439115578132932175386528905814925787545125246023127756457254035343057260754067443358310612781431962450370127519310802283888735862188844883231754920159816077568*z2*z9+3562578601437230490298429060529327760565805707574070333230218079030840164545798241590453133064682356150954215713194462419435874905520937954862768245610996056549951863117707583918945408*z5*z9+7149312108427941106535416500014385855176523070768736586762850465364008020004238847287019517856979498042617752139251942295198248992048741307591280308344456964002751655768720529288438912*z6*z9+114581004012431143189758515762139350771081757334483317211132924263182111536218724274909684902767405757229465369320673501482625366351459097769087513397930861778558733604509532160000*z9^2-28925524573549177304198968342736243393686787498897844430201708898570678967381907753061017939718867799299062265365734431630502189818443974141566638047382635957135748735309319803641995066528*z2*z10+5215142735965497655473832763731251746369542051392629267341414483967596728340648592167205911825775741192350295935096792088992982073880408244867801903756645363756662494646655415206387526084*z5*z10+20894327512413150412532817806028605080841984616059755984014321758593675736772040593296754778896891378569007415294166579100524261063305675291708833758821460180665470137864716707528985456136*z6*z10-36652494003850621516703438811455611223825998364714830035800955417507921142129849515648656018348745463751361886114351428008143301693916538836670784671416724246271749967816723663452113152400*z9*z10+58037822364547038742241346997933751672934504435487612584206111019431003963717439478823424907066882871868230478061441216421889626842258672528866090816247762266700580006305553625863066467262250*z10^2-127827175281521367663090884260470631881411180329068572106626545639934514169536388185199195268826807399373758206650788099220589765787301972850713084518998795874014503912912042961818376000*z2+7884173444500847252821630636643595986451069135237649085862055799290717235046780160237637831710673259849609064233020409986686927520280838321672787425903247484228275225895658648919190164*z5+65223941011388026243678400684222143318112116955669425008536158346736339104713212246007786893650710752997094151175987578827312782089543386992057978779238694946135814319200895334827104050*z6-59709683796113123023417137628528627602521722711784774329530260424631268557953120503141825789347038954733263063344205932977321671823370038492395141445571886772930758672303803186591842376*z9+232303886048602674276714400999443970660639254396529465075057266170706178086090785210956195045979850226723179256307178386053219217552847927864892802306246049759584592703110871702041902347095*z10+280751317782263605222259929725270810564456882399332562257258006297057184436335240012688301506420426097915481768626367425090435206662700460381749619292400884641367201155362856483516056766, 339899134091454926146798923647604769559644159066155996197822742252014378004624152232920915644319011729592283998984400*z1*z5^2-7181473186616363878017239777962262181141495511959026030058463334215363303209301983703921686511884156084870114131475017700*z4*z5*z10+1666095981267579170156306116246755196129094705500611493951701439442961615932006779710244420313561833453093475839448160000*z1*z6*z10+2194137658766203598479982639528103084885949523588397799395649174892941594609309610285953024617509575317235305547718348400*z3*z6*z10-7327567770042412860971677720062020196154573398398794283901239716812899693358962045274936520254961359255769635274231215000*z4*z6*z10-52105953698732498654327885548185314331005504268763280401463611459598198139276923827403132983008986993745576674874484800000*z1*z9*z10+104975041974198331048070460216341330328904551619740360274891013204166212357890464467085273663138122543722748381145818404800*z3*z9*z10-53539545495745023101980143075961910837877684162999525109672145238350620685357891058149070937509474824997998834205680280000*z4*z9*z10+1855165730216593417526788810588155913235227849670723063526641983452689846193599370644363996810109921128914597106710863750000*z1*z10^2-5861483825753353431773798411926702836264104105091750634477439828438606065571007491819267712465187057588270024435414164609375*z3*z10^2+3724510047311454459312947364611708732675440734688772649073423987620756564570963177782966461164005784271682210900285043045000*z4*z10^2+18492175842684366163406673959451392915194586701663352942723346380435476944980567302319240592748910840721130542990093600*z1*z2-69971882404740886358629112139398186530936315750325951373304392875800173005481019106077503572556314464052296361730671888*z2*z3+49228825145764676206970225068307597239963968934840325546088199855108026047516624417667436822835495102295458656655166544*z2*z4-13987007240984477847821473213557812356189285266252644433025861512941846158849005642298119612338581119543659386764825872*z1*z5-13655262372624745218778596250589394175449504161314922763929446264309996776161227783824970959926433530416093419635894072*z3*z5-4852922161991170128921080777536113719501258808929606893883957714948998621913952047128672640333454126172432455034952700*z4*z5-12729468330441032952214322651364895362172577267571808177052122704824485748521978601103677099167890502664500028290571672*z1*z6+36295237054185052724155665187694798359968527487921111426976838284797649634876585573776862678689121757687627029848047272*z3*z6-37513950687661601242323388842432472958653380402222162289232519561186149503378032647979224147239093856084463212575486872*z4*z6-241607819607608155545968563956027373136330072982848303247587235234551368728478502967748307527875870920790148574419468800*z1*z9+480878020828461454284671704934704689839439112550613655460413265651733854048823166210388745766749401008660172411554929600*z3*z9-242262139836328342316112685555046543768589381751277484348165119446879121477711391468314980111858588152411667797026020800*z4*z9+6569356015128621420384072115701671854108913602717387341560758378916064785399159547674006478953112500224435084299981960000*z1*z10-75561623035203459631649133862678187607116912951545965054352087685207863802814834980461943814788965555831267117831262579550*z3*z10+68445872799741631712600401897794818516256610827282309329395617867621406506423261093955074851248431125962136507529625605600*z4*z10-4610579450606218336274105172950623182381961402113551752396328330061205752064830525562368651052585167346017491371527600*z1-230955084811265040572456115787584753575868613943702271590655013856016247576010037981311213523595587188435252470924968863*z3+239894155476369171403990255983671004709109964429904563719209521624047008451598378186128318204401022627139725509635971944*z4, 717163382603515940771390254787226797375460974594242984590309393630326839080350172850551097688941821057731091474567692323534324977412738898781973775929980767287201616624009199540264960*z4^2*z5+26505030604933744267023351357834509229239401902294498527715492369711872148482078140412354615493465507762083267502794847527442527905161240659128800391321085427650707138853480891148044421254400*z5*z10^2+41060255586537277569637039129869326231236999190597783702053529544602934507807438071055185997909157994797663223233219335350244219616991457296677953357844014214832160963400869190374680154817650*z6*z10^2-1199469253535005369054638320177811154482335987335882686332557888513958084401425457312010671519390941239570948929836284002481768493918958501383981453542339235422710933291271397464384018271015000*z9*z10^2+197299227993263663162563639047509201128598928109463104390423408272143917871810931679362162249515970025671972409152189316420268022372642347548561812990555280142126422606982444077208765937200859375*z10^3-337890034593846992476553936214910129808557627572616230465094252692091318036891204307980695748601858965566183907319187282425446850591192416839435763620276833308857009403986404056062081584*z2^2+29909920852197255889389476995186940933059665267067791106682675128529000702095857558820712645989304476466637264601362230669854270115216382983470885613630798440716992813360260021608362070*z4^2+75451637110893502712671580396192195955070388588455529271607302032738803589882958463134993944171093290714589210559765144129254070788457682123845779984837631282853237418559471733333833464*z2*z5+30573996594922495553337963219990581525693058771815719802638197472485118908775113469376941649493820198082336276479210307567194596756588602842238900100313727068735720300781413303704348590*z5^2+83528003689057052841501695864421414607711670794307298634667979246461378479184881955304097040369641313634921540264496372921969710547393067344898315560891020545593022216164239549303999488*z2*z6-32486905210647126068074593055373530082719694230457866409594988026542838343885505216921812878338883232967107727326216424098959575983524381286068089426788994816302209989634984403224527392*z5*z6-25361900684205357172787450613039863120147888759989472393558439415397283265936542625807472963423886045326681249009949388604792316981610686180459050737605666491180213192972207674703655638*z6^2-84326508285792252163158771285909441239323954884042680151360851068997186507480851177841362491796158909236661025841956418398046144247024673174345416826409288766614494751065954574201658624*z2*z9-43111397810197451120272316085075744924329468173534170122556020453183280877087615493783488024379638759097543496303029267460412892416531419279536528332481868133165274771517639561686985344*z5*z9-94376620361817521555257431965015321203334105223586046295698019503776957965353418325750438408508906765708797374590963898265332347407786593945899199064509724598907741607074387286100761216*z6*z9-1676499983111543595043723770664139169000922092758488002843726581752689632573746446409825302685296964301553360527837135044651580079550280009734607998285060501583069164861602938880000*z9^2-981547372633727270836683758237943151461826860833536216157582465396936409565152235568750318959689553019853943117624488912352630477362574459671286203398976737501863773585603453367085848961696*z2*z10+252052125666116123306586832172619063313366122854913839031659358797441299393823920576372712988412753664650595647849554536324181499339745371350296759040968657811264886115074060958916327872188*z5*z10+658432158802903877392588359940245989522992889235153845508353714092299125285195263537003547086106375444975560818610574791947496146682964047774147257936341217663028966120946745643560791884952*z6*z10-11425962474733415848049312626886321474709181755386202658109381126563533525951849050937858403067456742302616115454802612998097611568871334086903466425323008307569270598660154760880720500506800*z9*z10+3287251420348826736375929379969207695529899865193372129103457856015637919807445315321448883343612515720529688216195829593676557613635795651581042350693378022857041390154658872162445957382487000*z10^2-5225615115599430955262629293925654690659488518823417811062672053891404821031946565178955194530229592856738093399454858951188982043537342887630930450837807588220940825130743285993572750080*z2+765903509495806630647891991173661140220272968513080154267647805276599872657419619409534165378723346733954923141541469007050426766386743560659708731822743087726328558587674353929616860388*z5+2372826844650249499408426695556783241809098391179704142076084534416602436046361004348816342189105775325382685504728213545840214939111749615777980023148109092190938146163000282670897764390*z6-27163035138991552411781258819308065871256756409805079404217765772182072112967642910043439954812525230600430673606497441246854415729251417596599434887229866075248444508640392133677504380632*z9+20195588715673218880426110420090502309468049422540971134446748163942906006357072331672253637377135857251173997195679196075516658367232136024771679468777737373036181597853653935119218469734815*z10+48748934273377907635582745421138055821226886857594084142873368544505729127272894317853616412586182401431799657688334477247188594976175238230379337892971678059526840051555060947886485731052, 12139254788980533076671390130271598912844434252362714149922240794714799214450862579747175558725678990342581571392300*z2*z4*z5+1872725233425743119242244198639072823696782650164211365775981876974395727482767813173232625154481767345132548870335379350*z4*z5*z10-1031719874516157631546682510888950829008615416708268495169544467847927770343262985682280938359962756926863714960314671600*z1*z6*z10-843443260752907844779604018229566657578815430724302911341135896819120431688086742957134046825104721210360928674494288525*z3*z6*z10+2092428347473814809902021329652926725718186849694615959061602412424545165187642781596194799680548029849436139184577624100*z4*z6*z10+19435504011420828026253160453649956825546945791315034430774733663231298617538583886476244485390801487106109902542167160000*z1*z9*z10-29368753720479244773036853314595806509376809555549298234094998583109012171088713088072495199249781700106310027005475063400*z3*z9*z10+10079342597443551653709794341969756556014068917573417649478432789231366767541491653373629322241795502084456806983010485000*z4*z9*z10-1019691422794076678617046216376559238637316614173793373496161117994243315475163240294623689559276186395967796104682645781250*z1*z10^2+1587011960320417542432894520359106477182848717991625930113546208366437539563905061165024827063749774990797008979817186953125*z3*z10^2-2892086885157298756633790001273098180580794654829568624833744166209273766718235709432214497503537803489147459716346899910625*z4*z10^2-2974841279694702846597503217235661013915681569587243616903918931718358963281207560870570243732610381613196909415754400*z1*z2+13591735641796506853442459318774051194151791588752811838172435019286069947341462260889272153750466602483839485983823188*z2*z3-9183702210797394510064475891615542841742684175833425441257117211810828665895133927479363206395036797395379774067515944*z2*z4+3371647033314865384340533039964967770755582034068820727235464175899352701933213326498621529879693303198867525632747972*z1*z5+2534920364482065792807142223238242448874538504138573282867295473740966229593449983288965890391669904215051185542599472*z3*z5+2314621318904994053935327014460964894337942067388038336506885614031783932634964950761857741577322885676389395311702650*z4*z5-1853701315836565171106608584819901993505733497896660103048015366373374212840521201299103993079468486378440861530714428*z1*z6-10405843287755006499338714843861936387344001512795568783271619991359865034517529511315937651358401030185203445703569122*z3*z6+12793901479249910576230505629898144809634447763927044830320243362439656076405454606048892840378420443856040104625314372*z4*z6+88646324069664402529516595156917722975962243625518855907599282713254923663514478659272852373424728861041545969842436800*z1*z9-133842357948148453775903758557838950761588780309004491365765367680522687309832239267382292486565481611762143889549821000*z3*z9+45848038168457830433790978817886368391419589384378303820157190679260531247171858886045903951559264618197924237933703400*z4*z9-3722325259391138198768413795882712059145001902754566354030944545716273337032237589207210428972345536201460347735923828600*z1*z10+5686752883042251773928058692175687748712821548076338127350356066017875977279829278136599943463689181700158670112091167950*z3*z10-17545650539091140997128094434009869745878586862262399116869266843633745215188422613103387202896696223426110964874929553750*z4*z10+7732601801062176359026391918965661209647225834223928000127521286990712313064817275249041248264471378778084314471675050*z1+15278995941695581286227086350628633285056210594599402463605585141155725481339450814431643003580955712629968717319697613*z3-47061537957245707580566708842884001491877926496461862846806358993983679550993255254165034289604023694880527249603565369*z4, -717163382603515940771390254787226797375460974594242984590309393630326839080350172850551097688941821057731091474567692323534324977412738898781973775929980767287201616624009199540264960*z1*z4*z5+97483099018709784120223995443271574539028177101767102910677835836718433440216214951301761781220311634193541230425494151016293241862820534165957938196550191066989318119811842674374999854598400*z5*z10^2+57799834682156614243969931590881933254619244183364264789852227088743687304247623341049534939998737482109227489858043030976746195807907680660227833395196634285552761106355625976921852062183650*z6*z10^2-2658070282417194722435402358436820867313456475728428057598006089625445416793090803297147456168510092238858990242156270996325471639613854473737809213438120625591868077902659032361719930111215000*z9*z10^2+844199380341587982366028618902540485129097689190634455692119899534497708793839105233665591822151356374917077784953582158572288304698377537361487952595287809518147347860452222818390059514321984375*z10^3+365778604324161822134733965697602936478433855833756049310940146245112311436747009617046830004421050994601959177976795907208215282462139857735823065881709961086946865183237268450059497296*z2^2-2868653530414063763085561019148907189501843898376971938361237574521307356321400691402204390755767284230924365898270769294137299909650955595127895103719923069148806466496036798161059840*z1*z4+166741941150018195651739858778958011570900394342560685399722204093536879123954527866363393185771660050886928436892529698673227887490509095436983067049943013141021948897322633356235722150*z4^2-94608999172784760537027315342054878558321723616320759269053594558366137321077222481233223742320623768284644306100386305536762344714609940987286398158919227340828696800418629108039571656*z2*z5+160116162235937988980948198568873090119758519244992421372631392708090105748086141547504538750608632772543399431083072279084632197713255298203956208571262625482360324729828249637264583230*z5^2+156055351219172749658818079781152847178841461836672003574066099477159294590285043508941053902356189076076102401306854845426194712797807612883453243485200969102907409277411441122669568*z2*z6+47049503501145104707588300313245121461404075252956733887411145584376121806974134771589827928317219017367134103010243620018756686909601748232158516453540863221747342209758970142354517728*z5*z6-165727676287134028333544318974531363353416175173349027199879833905707271823036361520436405605386853742308646863554515293503704753032480951230218981924055902033809281218753027975749319718*z6^2+175341801383840390785722538766227631464216682745320706581782265519686370391862960739054133873222393828920470563166827232149755373358939671021040932421588328944075731584620174940244462336*z2*z9+90522036076348200315060398768404701932582524839816635726370300378612551870090148500598049204458602698344477225404129322104731026442491023495311823462968823525648345870356625176200784256*z5*z9+194153626896991673551726714268577818959542027928376434442703802664876397743939482535429177926177434480261584166603916630103978056351324017928173876400311697561764936000605086097042667904*z6*z9+3453840158367291733778713370863520342868138987594801833894668213105701865744043530385505092754816415537666492209189714813749219859123467980540317294211781996998077568828965765120000*z9^2-105737775743858571514276986002509369601643083708544053336944172858405733071920782897504445824045335494095067233215070737952507369351551749901370297052313412012200876181483803691515294797216*z2*z10+682219876131606793555011931771421207553758660300649732898999883680195959753907542295327255070759347997223665364426428280673320270500371907977984547377831756228945979708814041325919609458908*z5*z10+493946412067997901761249723868139255470043469271645001156838488549597109675004248242670797417053716659524367763093572455342355929778573949914479077626928047762919114560229526085255503391192*z6*z10-22255251217973520519406958212891426828377152366043191771714099605264170870369423194621574236722671046195757624313583120334906355196852549494406360154987256316579069380997556853545589725866800*z9*z10+14587720942508788356585649162728594838741122747444642332920941813600351159498958161586461920944262067737070748956294938130388691469792190648043332794795750858742072133153380843430180939145519000*z10^2+930121966386925522752070334482986904034033839250218051797817819623432832930035867872580744008731561817410745566455442477538190113832501446141554891033025129152261930681298037628336477440*z2+1017578805607065567404076851970317054599505014209965538150071394493800908383946163409389898717120297495522987911437973017933434229655320600983950841349536968408136640524398752174245152708*z5+549370609322900960370951946430051403333142963623037025214570382760794231070264124008445339262468006294702094704045032089689215328045831954660315847835233434982521366327479846861469113590*z6-46254774642423773216958013121886485888813497265674376853355041340370689346392368122234398532477304420779770267873732691945574403419533504995306535564610175594405377897210749522548654440472*z9+96134300470100064636144225352494451690199420270870860758434509871427588157070752443058023694326228334281693985906271627181329722172076214331524223678566522724642807508987461455288081267692455*z10+250860460573080642499065964324102943043859170439461309301505741621747379271186904697010355547832297188783063004071091132946202842822632556771131771847008782332572560251639195526151701696012, 84974783522863731536699730911901192389911039766538999049455685563003594501156038058230228911079752932398070999746100*z2*z3*z5+13265775584208134207092016278136387491784682436854395281631280426964906952200620841746395210903382038411946190364366134950*z4*z5*z10-7257343756313411659920537128793330052522930766186078568955397437771735977444683862316133162845913491557872105683450028400*z1*z6*z10-5933187117876496719744049171040691992299432275084096768013396662355166269683697607069999087858300770933237880977140859275*z3*z6*z10+14785588207994021482401670452249523983351724176253942438723939218072426827039203532691134467143739508715123970717841257200*z4*z6*z10+136836347672062323698271572854544320278820754483889130846926530375939306546647698745699718618932118346739065247967713620000*z1*z9*z10-207283338495654105238811604587122950870586995260643018728042031807992497417535837926698011742109591380126418757327254073700*z3*z9*z10+71466790078841104595375958458585707281956364790796631761674568198078708493408765414760303652632210451681180764335735322500*z4*z9*z10-7107723461400605388788186371258055178867430159541629710336372634806218995834511347859230746332797028222039802903434877187500*z1*z10^2+10954927144666209557314567756503860793517142472321962383728309757849139948541856003737092324001411837442569355155827730234375*z3*z10^2-20366880506925693221170772980697070535466640439775116677310373034111540933156616050829218065262851508055454994884219717019375*z4*z10^2-21115345824139130153083742612325695981718434834064877291868069813200554855601864388896067601945964416128607779555821200*z1*z2+96556102850235653871762348403192734662421107968133428260942119909525353066335696220780266977696498854967991782905093564*z2*z3-64898466192156474630956240690785655582548548201744521288282794457479433283592790946269142299331875817881886689246977232*z2*z4+23947742233463663613666844575456277017253338371373885618644563414336917867585293323332322931364649726837579403237221066*z1*z5+17841602575553671979863007953510966451814843817693866280361357381535066721508132720561126745828454992497065080783424966*z3*z5+16446432181760282637499285557850446151285203255071850425588458411500950132251240343850747677789560251852757844023131150*z4*z5-12731026674219677763597965668972362833026558748844580129058725804602853283695714744101393342815481823785152467050197984*z1*z6-73575816225860799696418498058050905540236814488679846963652061671559781690389813100649903333316336861109890248217276941*z3*z6+90232583832522089690211413478788547291604991638042388725039227985050018282987117412084185173411482925917361847358995616*z4*z6+623981367258826551610813960088246122457989736028700866733627073384323329842387102318786788643583583799800315059868797600*z1*z9-944442434436233040210025165365292906654069670803997760642726373767466943548749701495660588335605300129321413124970716900*z3*z9+325012388214497410032581459894880179390532736330114328216503395079822366031974457568827441825934506021509587787430189700*z4*z9-25598117346581172696181979259267039140192470087049323582568814409805462727362550915655730457891284443515451580632083360150*z1*z10+37524351098897938824357581915325440747441424915994231496967026461878270733773382916393171437545695613983040327634243038900*z3*z10-122842122646186844953282147005184977221965000860426104543109984280354685974781025565650014111492099110565369252139116207250*z4*z10+55681495900561799714359284138978175434284175340568169964721166839143452130165120370477366503344541624245496144856709750*z1+101729740494655962399915259364252982774298766115296361118981022005870017162839419099396124242237147683476780930504025289*z3-329127844533761025659926775804518630989559428525843342837204817408717569119276790050609693968931925055117688931894649607*z4, -5602838926589968287276486365525209354495788864017523317111792137736928430315235725394930450694857977013524152145060096277611913886037022646734170124452974744431262629875071871408320*z1*z3*z5-978101910242435817802675255008623898268907855958289611685455249037387418030138072180568898524061937077824991875555440677729327441368103121165099348353662473951343231070620963897440075117400*z5*z10^2-1747001039205032429433211541198345124633955403002499373208398619509764886759562778063141645514669023474827354077209906346133911050840710116736993657950188780256159342433237852932286519188900*z6*z10^2-10906239949719313309591415608168497051567470593631204478485015907480289628930790828357954191551117828998853556248559163785959722873624781133959379214488307653782081211760617441357074309635000*z9*z10^2-3133422333853717523322787784146996871880641472564950872110817144715886756069755369365336598967484461917549100686848484768365696275456373635369571578179880145927575581635077446571599634949640625*z10^3-102172910981425689545615913338991677900877621627984160329175200069099479911122191265155325072899542804051873132302270560730568448803632834197867304857767566166485262481707209189999616*z2^2-22411355706359873149105945462100837417983155456070093268447168550947713721260942901579721802779431908054096608580240385110447655544148090586936680497811898977725050519500287485633280*z1*z3+1299491690452546451339505601414891373306196974392573596830652078700929187127572548295420925338736544807766775070298877066911752813013895161072534908918382326054914072994394765709598750*z4^2+2663859571769125744866885725212530360445835172100979825546024610383938321497815560754310174919507224045382450210361511038782577615866769163484283276924933561318168084309748097778692096*z2*z5+1351440342143569275696459423010071660184864906093278027943007414971823004377828836819447801180339555147802969750158365061708105803442515121972366748763633459398756907115314223747164310*z5^2-3502785159417715680900578998590156882705806377464958973812274404611062245668400876204590852170862893679596243620143645690441852699295674045389567602464432126492069755029785009169599488*z2*z6-1404760457348146067356223582299193965333178257982195584780657115103103168580391028754566799452536537391391588383408159223600643757768663972437141183392524695185216536634661348234894528*z5*z6-1556711942428514566323530860711504523945031196128662314401540320073780346819777732167882380318577103100335567800831259049531315206108820930571551803966272597961046544777619516637001502*z6^2-7679646984088704190906248237307695906677531885487056902255798179652826065144423215089349170882091504979003982107481919881093180002321485980677716584598017996790598268917736038545828096*z2*z9-6898522536892859433377398308600377258984645210773128978208981762896025316375838910548352508572058657702191219020165654007584821365298131134899110717541182491149611275052264123027878016*z5*z9-14055633523348278686061960709962683036044869482906489231194513393083307769699835325817524373321540663132641323672066515915765100688307390712149487279376723521754813336010809366150742144*z6*z9-227718849937012118601533501862917962146819373963195550091481913496946015659547147080254792421473101150733276191332867310725925073568705071043442097387273371411483501231843000320000*z9^2+40506379657507734026215633535382988318474859005731886771757672709681719191883793619400327016074437927965838859563147302500826512319442727496401032958954487398430940531025094542572649668976*z2*z10-5323319683221287203441692845127328664108384653003070525071525268828680550234141914287960228424224136471923217767641204764945953817172453348746847845929331873980123562673642024043206165488*z5*z10-27563785399990014927016661446819694874151320317794955295054876563252928696058870376393032025237245666065570977439962143758180887378313535228083832557975059424982001170295345713310856887312*z6*z10-124481942195470868081055162291322553106584012736967989716995676561672478843736002661029708650736305144664535491304307366773785877622538322326866263458475929258707406745798482817066606105200*z9*z10-14013620666576468682146828970241609188990489318090239665173099891793972083693631016541348631007876855686414139192942755843219396067020829895720654266996579866817583168708660682057148612189625*z10^2+180888875780538745233798602725540151333849713557849605521753512168672083414331027534017675085256499565981101387484687712421057507486871279656853486541807355033711539568977362008983568880*z2-6875816835998357265760234626354051455427723174705552476495873987369424297134687612376441865269331371031095206155528250262997846796205310588720511892062397792139546142274545758675567368*z5-87361872119239894798753095459401250165268764744729840583262820555885972672511430518297139890197124794720155909726119285392997781878103255449947778928772394305191267796424441112702056540*z6-347609713680870452875403947290213827394155801604469906547100815933411790220727729619456809377901508215832542613087765452397025835790354243409457903991254838067625917220009511407435639608*z9+197993356224464000633455636954631978374259120190397694843220985419933833587579645301676773971642714588515264212608056081870962815881189544731239011576126695692526407575247805906620340046445*z10+1160009415539637572487531379246337779222495218879465902599413030371095556925735671169267736038277564254013191575805243260209929211873512745009846575541114694938696834112140636323008968083, 249015063403998590545621616245564860199812838400778814093857428343863485791788254461996908919771465645045517873113782056782751728268312117632629783309021099752500561327780972062592*z2^2*z5-413296054766362532428362331756326340373058448465291855434531735851984907515644160247230649472893780851642593968869833854442608283407742750011589635328684352974214259621628837583630452200*z5*z10^2-887332542081777470607038418564741068684708143216472189476157651657987863228028245498645078775178164548704057030785800496153176441989837622204187470573806693870393751839157512659178479850*z6*z10^2+19568008052639815731388288430907036866470534621490423447098155319476939280039886435807710437728744666522557703392818103902904205404001545178160479736703216945713098896849837463437499955000*z9*z10^2-3000691922391218817997248531723447854132810938164942033689205876090960703530484855537135066852878924306239032443988216509850090870828684603381641874965325447404952379831205726255388822584375*z10^3-66256087401259787132994835393070727212057849827551440116628013109230803342037999436375066156492866122234566060643231102458570563902010229940352727954536273937626491119262976128272*z2^2+164593276471245824071746049812898942893459425982835821983497886424869168676294259832396482523917631753815885296869678480769579725545369045059721134026250169830309808463846146826106*z4^2+790470279860549070811051534911200296827955713566796749538146959631376517691651260504177477745015045411571630319154615123831797107120352593072506769423373679622224122844216369345320*z2*z5+299689353744242149391249577793289943992572652545888714843817146199233754584570719916005532776479425629854027946462435727648281854360910983093268154845955195587238745544223392654178*z5^2-527159017938135867883466854920282521328983843415868525757411225882061262858582247460213268552893165693822871251161805945751786263328361573281267922049360933538436984810427971437568*z2*z6-325058936014850431112426452396408439313922517007016200754311152004889274291589142526078754514851251642585675226628101915735163950352732102869942708253215956377071553118256255759456*z5*z6-281593966007574698971967683413385623007588794404812078942632031023427578392572631055991649567108663378383297619357400569108074253728124700637221394122970852258814095420743421699834*z6^2-1101299426383530540335241492112060355370084110847256834690333990186278035145460010174831113225375486097995158096475841503159450683528400912230606182690157905381553992634162052009728*z2*z9-571796788851544304901806208734999735528195696549014637970480537237532984943223954493029607415884606803876681662147916925825979625821477164890746123244525925777442321337557836299136*z5*z9-1244652600926843348053131476494863469111973294001739639181541846371606099998200420261229859728746664387449575253425519807636670565274556765608643684079104027079706722962973875506048*z6*z9-21819593384253076750594101337255058412357346252025769409976825062314993844660529353855382110872560540231986216684662391201935220900364215665797345655899218161877993202565120000*z9^2+18447226637286908937203257436456983502869779818673616495957209688715784861333653246732169965514539124554567998823803061804999999014842449093891138411338320340617270643216211214213721760*z2*z10-2013794920314718364782637153937139944446327711365205741481725090453282978400384545722713928726161956905313951454588158647488796647094569298322655935951529655893983980387752510886423612*z5*z10-13479780161492155044357021044117056006509492393056626124672273188212301478087090673096557882473752260587901569469035537256444099726155538342954909345669125632445717982735462159809390520*z6*z10+165521323968098240119015193899605646500294273800472396147806124441834800581692704687177848805117327594372829407781981370848677251674321478892720865577299552953594737657286017759663666800*z9*z10-34708860000838441352546104924242362426726328030973394443184434975864052762236172708782571134279021846711015395123634969639523550231143657028575919587058986788320538260015058187935286640900*z10^2+81452219070886546990715782459595858527533029186005256473953601346361755789549872595371669678001756366911499323700477764808072566358986244364787366050184386284311305685195847052063360*z2-1011722327662704843613502122743783919006832259578392295109962248301183272020321534231980550641718072420542136686533833043159837046333048533579861563796488535222481447826144904635708*z5-41828215429351245042220955320784193113989717535895403530238481595095529329308022928094767763667911396755931071804370129372850496908653172217703449189270810267094292447005825341725710*z6+348162501781555428377536052564005255647861604838705713042012419859164172394541404452504124938778111871075592856128949097031284788866246035190789141440351841741698509814052230052001720*z9-109726011272597151725003947981692951596086696259660269393920513533841614696824214821260690616975241713910830606705308644414399179492454378389823287173952806413230697432047475306059353343*z10-32472553759704826522364270559339306670108826433441522701199123829575299409081569888393658040722772531250847597715109504038454120123208278546855922959647421161907118734060210141644440, 3398991340914549261467989236476047695596441590661559961978227422520143780046241522329209156443190117295922839989844*z1*z2*z5+531413008172105661691147859127172816145338614120792492743690968510594367248472825561165449295084698776442197467476615947*z4*z5*z10-293605072766590176200246619569753474500618846002911797803321900290617320932641731720135371086300142452580929985394601008*z1*z6*z10-241139810800109791824994380303135778387008107711344789815065897223735248786244429882606073370091585087300646982937041199*z3*z6*z10+595249169160010445651810315235264507849830713903473176579153630932112287502591702223988832603274096794355243252569222094*z4*z6*z10+5522239302242312991767518390130595934200555001184036084085812917594521169052676249547110865232924401985144063709163034400*z1*z9*z10-8383810248384329722726520553302820959858072751155619562696180811035049791523573716675565147118078613614254409200738183556*z3*z9*z10+2904376689950876782520448490343341666219027587504340320847313922403494722117704878719239878085314467049667252158879372900*z4*z9*z10-292889756320012774672338744767223699730664995480253817658824606292446929945180844816105140530082020894633846147927708912500*z1*z10^2+455087832219303254857514925378325168863276902821222830415078836802335345909516402906912833169267606099779538562657075021875*z3*z10^2-816627799693025526957245454585745002860788905629277845998176145483122063820004420032193522248037865709562148660456536884875*z4*z10^2-857188008856755288969835167976827689943796615748602116750390710689547910035122269830684930830525199670959141043732696*z1*z2+3842601929399203665909240082569528755994314522247973630830227059904452645236087529840395841054017419870279676788418224*z2*z3-2593700970350687752490335511253834157385313179145385966089272430920702497707206464816352918769510897228770986800166324*z2*z4+952404092143071667200228438927480105351032128496077197181490043637780203328040566686416990653402683474738660296141870*z1*z5+720346183872868362512042080974844826302487009758832675043230742717590147019452846303748070580485193534647612449581996*z3*z5+660293707775329717926188392007549627948193574960638607849641367073972018442368629634783257242609188497964442132662697*z4*z5-527918102485038780849084969910046489874530489113113873594685964128054514220843007724365684422835328154253307714691538*z1*z6-2957568682393721907224983349859097389345950371453468124367424222342230332502570891705644055158959674869520289905289913*z3*z6+3637165567514024683792557476808463177660667281966034307097181286389061347715818593366363351734057130208037228949117934*z4*z6+25205387001214280128703466609345772555508101016460158400766088924760012699249465636680619421241898103100000048276367264*z1*z9-38228771774190791880837719612960253643827213110011749227697686110664322615126608408325853469831856555235401950914136772*z3*z9+13214423835871171735861888753711701623751437823395317562956237518030154383492052568963307834303278608976020826166362916*z4*z9-1083904253165830508078776909157590075938123221572162266054234480754068076049692761443698669067359618573461186280400763318*z1*z10+1682336014013561807032095760261109164739875696925915077533332582671786460033346659977194367568266622593005816886978957980*z3*z10-4968930523231920141580975869549868765232341360354729477275329837615709145853573771254952252171686835810682171990428640714*z4*z10+2139025467528040190885555923788130338624882244646600978691353785158662089613617456618985577546720400042787955780562158*z1+4547753371776224305289388832145434392264405944025600863738527399914019071744303388568383000135191757925948652507795221*z3-13393884011895744845672586105065471648189774051847359384697792179723992809307672340909155288893919589514935211415603843*z4, 43507089163706230546790262226893410503634452360467967513321311008257840384591891485813877202472833501387812351870003200*z4^3+2444235997225485603181224425054582688866671001876808126254145619884467722497742716571002338518637977160301109379133357789675*z4*z5*z10-206466746731196038733049727863197054214131321358162479368961078088459848079444321842071822692740907918067108277874381411600*z1*z6*z10-211658029369460095596707117440515511770787691635282076353020561458436499759848719312177329389097829666789193507968407761000*z3*z6*z10+2115315644994091913484097663908518881115788646940486506747730914218408304441541809153803664994099096484562406196560164299650*z4*z6*z10+4774996705094576921036843356335293986112520492183896036113224584323828847963699111376598146019839641501686054303151679840000*z1*z9*z10-21096032443853351675687761784460348851903158410069706603028740454247942661389278749264297059588879134641957252792942243101600*z3*z9*z10+16487914236739607615679346587022241819318988246260198244212659636000178661854672831025886995423417328167651742373354625540000*z4*z9*z10+609608522621912636730448560472455279356965680133377984749243292344402274340625842564541018370158249452549237410855308905078125*z1*z10^2-2550535342971144942493329959958762152861668542302296993179596377720059515666250053585712207553682408160502090479238868301093750*z3*z10^2+542113216774734822278669281044047013027182334042027827923462115108263217512093120439275257639734391079854735552763614050975625*z4*z10^2-7651677534595375778172388432761400460694288869967431001685597480700490584836362109144509989517027084344090519264467551000*z1*z2+15919270656647240694133699715934092023428210141095835788598101636084908076098031873232087655070933974604655792684643584916*z2*z3-7313343782179994154350010431800139704601916057625891086956613822571580229038257696526958698270105194906041003050748990908*z2*z4+4982618414235841558800040193908721021898391663396667064769129339246900616909063591493972350741032421522951148231790171804*z1*z5+4381460623519923405268304043422632464586800933801297974307319559174620258885543268810833730368639401954705599169285557554*z3*z5+1545674466402119627302245810446682897266376949390632250212022407600063762470316806084511779055493092930154132434626999325*z4*z5+6452609060225880574300872172818164557538563219509217681840657816900143729172265471506833743519407298809720690766909811154*z1*z6-5859374425928355911685292622325234962098376456434969793957124093355549796918651631308453518993893214675655938117028692354*z3*z6+6556513764797009616860978658875842777241133958763936392968161343094817119965418884735228985210810863906795533894410709554*z4*z6+23532378985608442840027458423576252386242883631106472787065379520366359724950533488048022821977455692398483090779858860800*z1*z9-97272143728000590719469712052619015626134170416879262174445010858529459958532271297391795254294285146761582018112985405600*z3*z9+74484505411304891595419385007875868047694462429692417894983546691247946939465456104806641679307838139784120434041765949600*z4*z9+6543046704299085316767655492090013240828252750713058839726194558602098911676627082403022615965276937733228144046380584792650*z1*z10-30949985602644647579069706319830781636279416815228362563313116843857740801452913292185767434412000413983886800866525274286100*z3*z10+17604445420063337936741892702652860378398304411133231061302661200499014934494338336769592995211199140537480778751736028230550*z4*z10+16205987257584766781878082579760465417249129605760223800278327468885583600318127048301084842547628911156377667993749500525*z1-74294602753551052539943591049907129413486998932040595627702740251434591194018894259615366521027883225751410901316602170234*z3+64732693273564287052851354669718577130324798011105870702786433771006587490787652444027230652239664823125499345380864270617*z4, -11952723043391932346189837579787113289591016243237383076505156560505447318005836214175851628149030350962184857909461538725572082956878981646366229598833012788120026943733486659004416*z2*z4^2+537335510060071786600757494298470620994791343074751525603865947141592860950432612037235031696537695456830164343244209462324348354073902051527299705394585924598071374524640975175075997684800*z5*z10^2+956295069390828581375560264392209833253102218013287140776641716859266110801850197243717334662552440028384497693464444357906981339566132439751643697961855082376334538137809742601165571011250*z6*z10^2-9414829117702309346502390805942751183141056820616438744196658318214239010228614543918774854601373279736196770245767307325085403945038694243473632445700853592149261201300993820122269445785000*z9*z10^2+4799733904712561140190334887884280743573472061592781809055048062204664175706010913132806445124054744969977604592409308351959860656052121566276859552501998792877895637509315550277676920829690625*z10^3-1517149850636904811743876718023510254738549643902856589837906792973697394293677627752027970258194360711986413026586427506732861608665571794634589695451592395298173860997981008235728496*z2^2+458131287226422063814354932526110401273379888416575987267437428653533083321714639056862160826620884657006402400380621994058725510178672406239812587507637103395842576443104846728633018*z4^2-59889730989140429155872257705621461147539574620984719403566402671496153210283994204552479611290520664949724322027538188194105876319901798101305575604199050864780237369506935072950568*z2*z5+441479844380229267160903096984740746924490750089031796894387574646730011941296214788328289553225544128272989578581064353650357644193086498865980907476747170127290595734081543487052834*z5^2+1264637020473301720525904091274711176809996134308701286231831970430376465432615613764146376333815734761452877139533669216281240679740132313381957711511226892146934867526714650763966944*z2*z6+100004378322105820319778415066302830782599240273624899224748312043041469150882833206011428473289144757487996506328535269156044745592552045133059852870369055307486182441168107410361952*z5*z6-353746551707387398132897253206596605108655992592805177259736379651088323836519706255912339363430264880420300023646539847602626001859380041059715512031461773139254862998156339348716858*z6^2+1547032291954971337878782406192264423831205378349615690938196123561672093307110682105723124069602201910871436003128570658485425432009397743796064304875389919823824997485885785286394112*z2*z9+1696428306471783009726074301155138512151370466343983069304589627279084474798408795368989940754431735464445718402027491891833594536276486494768423922265685669282725290252226955941506176*z5*z9+3383360256937187667525133433072873958279561806118827465595596025769832860685904869541091107174366045887421923645536238959436361421123904508693620095004101167822079957305114296944442496*z6*z9+53581862907731862408737878493975879411077617135264508164178468088836239789777356502521785273553938568672573597789848961187246279582867929622976130757361419454475106305101086720000*z9^2-19883652530547104696847607837059895389210255653358722456211845082543590306361832398304948747985639881161109268393917116874253775663431892014721161819869354966255383023054975088524390871968*z2*z10+3534251390750089844736093951016685936592408802426801635211210431070986858487561554954195431160699200008284794039409634789707728239880651903445069797065210815323215392189564036217933788900*z5*z10+14192866016729668757747133188836234605378528970229772326386481203675321824754920848747216835469116227826251451074843185795681594306371052816930416235077548663051884737036936697687868765816*z6*z10-82492700950375405084055152934536130656872144781224291158373685001865316987485815975005535368341140407816865277487697563386417691663009820702374031393615718440664778313733318208426112830800*z9*z10+71748334328259208323430098697847280373344959330707269684847196752253872743364190238627812487541028180629460437690180252766562428390313750269107119195908976468625026933049182805809400394614950*z10^2-93109435250304855117412788868120532009004774830229437333616482085730137079289032470607238898378029331519015946561448057678136363592434943721675655574273122360947285883375173919411891072*z2+5713662680262674922972951667666303536589576260496204198174185299958017836247319112553687248691928147298470175775502290588555476091666581385797939330510620386655481830045385072784808740*z5+44238932165627332453028200750032277097779453539726924421568041463318459874555677143346118945024786019561020414011150184886537077535776940092690417979668480573724355094460509623332195686*z6-178378062044282437878456718118749884718113847308522256746317069183757787627922655530643862238408212855217854941628072303896969703302909304374267214479993022251815640724107659855047042856*z9+394775738686518682303480073576695133897452579820944443393327649629570056328921553096998778359829326211418674680164312955884692413063774118105878728472342768829378922091683350285818688504749*z10+864039107028466399712052489998030526963806437364710704606959514318873666949944347602366884769937295379588295395939852456948651766476349337674954356791498583392502432490159598658235613410, 43507089163706230546790262226893410503634452360467967513321311008257840384591891485813877202472833501387812351870003200*z1*z4^2+4809880775430317842100077752787470927168939215817025396617021472569242334620535341640878010659216710693668585674695628403975*z4*z5*z10+778059464068226519822317165419841879351325076201538127770879777800764419816730606494574002135252924432446337252624107234000*z1*z6*z10-56242547931246924082659039089656473788684274927603957545805101736382391529343416226488227334335613705025508104534142397000*z3*z6*z10+3425353027178124275139586021137312619408911046959530039585140288394207226800479837512109325027772906195687432716601881896650*z4*z6*z10-14329055873506581673539421023810966174859845407235868141391049698269837103259533372166480885402191816801038373561591724960000*z1*z9*z10-12186581228334278934814304762715136884281256537389397213161873265865944467586290731457169320294930237743680863778880910973600*z3*z9*z10+26736931953298744320837744642057707569066868562477489576334320430050397699952619700985817066933893970873356144692506563940000*z4*z9*z10+2167184441463232300373264498998527881351620686799436744047360429592456739898978928596489722686465773608832272010186047492890625*z1*z10^2-7024062107159386951924247692757300077145246563713948176146861203936821435901938277495284062982166421861888812852656640551718750*z3*z10^2+4290371362666717454756784906310095135670692735036406617037793898647111440374650574471579593010869689402595021277637373022868125*z4*z10^2-8163269027785018517388297086115624622741621031595013784619758172101403507617066394143153155352667472366863859253505156600*z1*z2+47207338107543492123295921970539923815977437400152916380306338060174710107758342394293983740077748831480230562613509742244*z2*z3-38533788708285469436323506526395728264033812281590642894825680624055360137469253288356609062154233672597792171524574881772*z2*z4+10781997064501133038718474140115149771473758085730159530110936184793217103062362683682706763842209386561374049243240012236*z1*z5+10288707541260138331773155952739855438345113897401908656348520812333595237589149057786789411659021373466690078969107589786*z3*z5+461116534931741971579828721274574196307256076384573118514301701410579181710597101153570403940826348055417378283831109025*z4*z5+18146132460696428970686967553223586754507934641662286702681082330417624486673256092031011118490220505142022163978971245786*z1*z6-13774131653667338330961521816675709214199871189906389965529057057579765490253559624173214985347492441927615490124496138186*z3*z6+13683814306998635239188747527582239302861863058942612149654732455827950398569147025232301280499995247545937522322862558586*z4*z6-60943498006218541811262195639380181836330839669677986050486175959948476944709703203195182289262165811938387684031686176000*z1*z9-58493749472855566604370313213651336386924116166329847125932858578216336345172115034611413798197698673336811413457745104800*z3*z9+120424805403339269637597461583873637367079272953801137480325576639343531350157447777760413577026988866630069314998249117600*z4*z9+19347899589374901774580270566758686855436074595516389132906168957136898411274481275582002733115839292159738144425820533595250*z1*z10-62588917528802925469892644702771437190673263317249538685365629360833112070850017660660144251077836707159462383896484202944100*z3*z10+45915038421819435863961398388169661690553467946755973704060501337682207707701831873693917736792669253623059397763264646635150*z4*z10+47566383841843984765375671307203959241409660433132609495289040135270168661421617278908613053870911601835225373727111132225*z1-97844629917538288046283317212225103298900879195808255916090215057344534872286317144305120125467287973611043289285992051506*z3+82699376486174738836329768642231715192223792322643996564514282979881636995443278683966495726201359501521795520011659402253*z4, 37766570454606102905199880405289418839960462118461777355313638028001597556069350248102323960479890192176920444331600*z2^2*z4+132315565718526108755258139215127624269084418701435237377667181097811110036233091460568061185402325287228521256625669125*z4*z5*z10-27975682030734609019197004549403998983124314364612770848892611150881598675429950828031618955989086704514655448482779200*z1*z6*z10-37904352041740073473391456196967760838423801734588060881079989205616586554830440525477058802419552995065869428526218500*z3*z6*z10+125645248998298063052778022210835958752858120649241546695223229377721692591176628189517283728367773227150088076616276350*z4*z6*z10+1238286167240046429081740104172488910674548446166624267302269508981944067204733070423000903791371306807379932921236560000*z1*z9*z10-2241804457594315469033340784962783252566687148428885177229772076209923259014473581695681466665439450668413102665191037200*z3*z9*z10+1011501166701484191820327601029266917826377989647952262756967083542588633761112640916136733617908126451871648652351690000*z4*z9*z10-6968150414410722936700685091958669604505257194023597105088925737255163271642472501748103396648577414108910168244543750000*z1*z10^2+54669883016893895272285481908959807724147012660342874775159670324097627338370966191146013403281934846483162558221786171875*z3*z10^2-85113367689887079607784935836420595779217158193501138010530913040846297104696630485495581415737173154231814220162249857500*z4*z10^2-301850439177415389373480715431303499073642494560457299391249934935214666394201424447374554991905830110840741713167400*z1*z2+1280522053621604355080778236869212588457807078734013446013504221528316360262234928853845354566913764155126926426668108*z2*z3-763043071268539122121827351836303831117204910968616882221434694938092277112980413281686056922600995015519411902820004*z2*z4+282683489065094236190815640020237976331653030747827459297949873540278991822244318604580419426175303683376031550309652*z1*z5+202676854469991187355264356376426414197627853883130093261272600949394520598538848964597228071452544448210526707053502*z3*z5+120651401190329522074818942525002924357018995119054018775583556417124563746161025481371082556881579200980676667964275*z4*z5+230006914107250778153794852488407438630932346606605115810506807274549679738192857423363457606640507821316334037972302*z1*z6-691606536472390394984979708270752537574001883624338108213122205317879850622406689372801823132661566335359612783757102*z3*z6+644197708990223029219820136443659576342759851651036100790049423298638191109722910294917287826870536667943788658589502*z4*z6+5628999355002479411892499891757907151823671707701445959989295230077015065054583894610352176014949551265870290521462400*z1*z9-10149870661889013338042376692650564303688163353263252080954020943725455771565107342843409820834358835160013887725216400*z3*z9+4556497660157148323976067008926079478459269235319632442784028422553086086880465462522076734203244092520940529704237200*z4*z9+127356498780679356234835129446541711920720915841433125834505171250407558709638086864692002118485254256996221661556901800*z1*z10+775006596538457837398201586504237725463929595607342132033377917421905599616176833374163599443555933135476072548066523550*z3*z10-940289331868624437511849603999242447713825135583884084988376469700413265131900526561417412211175290705884645113863317200*z4*z10+716189498230506429598429689506760777657524761893931126540216506747585690764315094286652498935018118320556123628358200*z1+3982687616644882130823335814310333532711277013873251045854499595665662972219191307319242345169686549158527605359606283*z3-4127631826612200901771623447169606791542629961155695616127869131213138659898119740332398975347954230865230885779210404*z4, 956217843471354587695187006382969063167281299458990646120412524840435785440466897134068130251922428076974788632756923098045766636550318531709298367906641023049602155498678932720353280*z1*z2*z4+459914495690194531764185772046922119499633884904363143518448807638683761317035659598684919055098917611451676663977950355498362052220144624744219449092763615681967885110357445540337420051200*z5*z10^2-67168729407594786718711116238431039227810798955922016172587861752790777749464100121146043463628043611277209151005591210766434169131995548294446091181837553247290303364362916882959301601098550*z6*z10^2-364346498735267300487125160499050556637782604426133809276102701934244194965543774197324300668157524346685078018021394060979814557742258194910575757783009739099623974440013238651026039744795000*z9*z10^2-100125917409575468576742990881742874952822219820191130558450934450860276181234261755582660880811671736827792048101166061988304728880546724902637661557168439105602369009299944540820169947914328125*z10^3+98034947417451649795836680260271218960821645968331458374396141291536084174611318131755386553659347983840410766153696439717630270311900695104011646516744110647785552304460107516120299408*z2^2-956217843471354587695187006382969063167281299458990646120412524840435785440466897134068130251922428076974788632756923098045766636550318531709298367906641023049602155498678932720353280*z1*z4+28257133401273053392303540865494827207532719578657992145382002937538089128672419814845669683853358639145865454009829208129139141286860008159679763358524463892743206637204212109222125470*z4^2-28102104594065354415736068060577651948057900604648034791869080562431418647570815568260428869373490777971777055892553364553001618814728487167034058888855462806919230379769583406280985448*z2*z5+28091622423141519539385359980284151205679238532399668075085463350220004520291797857031221736585703689776570942939865784854133438262775927803517827305485464114901097525264112440471569430*z5^2-34025983091531964728967665176784736132138315451769711903086967080799721574700758765529665827584190938428206142052755737727207459219410333588224371029359855587279699970328751755989054976*z2*z6+7255339444547212387595786880948996390990997597687923066233570556922554604913347300259509110017245203675951459121044575345954832561013802782424152747632245350143077331851768874834582624*z5*z6-39123350028534313680981761175179501033708172955083741222638722780603590750296111072568426144342340487080461505396843977185274244198254617257376292035812415455928813433608948560371810334*z6^2-99231273146424750482372464074833549873110255824009655903258298860029228913383414551093250375127175579458782761573977082640463139902261471496030524791331625400138044038615620472854583552*z2*z9-134698078055659195303668894740216440753257658200195169736528373709090049149989069953715223795096223129018951030090934459848409100531290708634694869642182886614587286504364125890843162752*z5*z9-265032476415865568160559029078078479897948167858726142656565041795084390338203087404224529213593165847552572175589074836274975972313705355922378835142725507609928997549700104264113694848*z6*z9-4108125133242672721840841890403901195771099284817671821158793312077783799537955271402168475680377861309153857810672102270410533295194674925730343252998527947488067907814206423040000*z9^2+1656751380953771709728713591123929909583681773548618743781201202210642221303101082526015972835280577060222078552175603497376628284586038831369827845074861401322704899922749965419162476342752*z2*z10+39441079868748401915922892786892698435164800518947046894204998445584624823941871712691557758048133441788608396894509255490019103208763535641176693327986612582201498923089792356028320988684*z5*z10-1136242991922212166163478001044754484459365849550304871460769483442169910552401970298393267802939916960402679819580558660001894306338998920978271464773356023073168680096832153523225795889224*z6*z10-3025508194168727478103241416900132760714953405096967860046577421163819725084557932813879803296688240883137323250834108223607792389195157851697394421138175635440189105969944311179208020124400*z9*z10-469304549389633228146458034970495413055482379937981487289014520521499864013035794984064348927175662981907043389395985094112201070790371674507808108234171327045639233459024739865110875081401000*z10^2+7794349459296924261467256873785516319651332191007236900676682162732022886744345131923295807695970209385264031581047911723046581092092086620186284153373422652910459973523287509967467823360*z2+138552480575272615118888620388001639198038898242654803782278659378176927749101213712817803941497771058219318023738413550456342279752275795217624414958833857097514727129430560484522726804*z5-3760623140210530515218781509438126828626980705205442464716431598970392114069133379940538013294541825506183772511074057263005902828038807147987383246738102723751573139863413036008281693970*z6-6423682925061275852550882251458409442025686354522224604655651567800471901504192748988165630894468644819050817989500055779806953386554564633569351579483881323460999446184931276172926426616*z9+4922696247906447447061947463309486370373277522443636243405301481116301489794039755214056377034367540033539947936214046017680668906387421498992086276812227385061155844993922961663281314755955*z10+28523507630581081863848638341995958160262916452364223494242708446827477565149025799306112349954767701949972349629848966338543464442906359747629924454999794693506453687894131997072467395036, 37766570454606102905199880405289418839960462118461777355313638028001597556069350248102323960479890192176920444331600*z2^2*z3+134679054915516079985037073752054929334181678552511351062005941560880333362466354425237860398830951817822908222787410500*z4*z5*z10-29576018661275437398841438317757577551894626475149291543300158697341848524770599532227147919427492345349210659283449600*z1*z6*z10-39215724336634470394442698720524093289443330865527897148512982034970152030831077301680002498315029659881497785216518000*z3*z6*z10+128527173738173017347592120868888742410671113836888888035436433258239319606008196122397030685142217014262262528840243800*z4*z6*z10+1268422913414263405290966605582104568037244782242213812108394801238239888700426169692241433336923598469537217012745280000*z1*z9*z10-2287507312903777985977590592386967155967118964910772312875822238144239845344093181634681317613206984157475513341872033600*z3*z9*z10+1027296398552343482963054912405374931742667202439533158419178059397236013747556908567591132631750704112116439757795720000*z4*z9*z10-8550123485660070604912783429999413744409226392790025340774612059912335035547974060511668518567652955476874423750943750000*z1*z10^2+57118178028695549707274512319633708948189008499059372406481852057135781545056244498048377395304420401483662236917423359375*z3*z10^2-89584405951055893004167319144576128926943558794335108610461272814040354280452452066555062435466800753946171366617946085000*z4*z10^2-312765653318664041046829960758676418914013448670102379539560256986764813246885261828478065869726759631812258672711200*z1*z2+1344459755046595736709669720024832254563437190591847056512053895934662102883711836533661767458853140212298742142608304*z2*z3-813836197746632116321304348181948696571765801642730570892064843368511353574150284461235553042648489219842142711212752*z2*z4+278440327556847413678628015106110235981304366451529962615974393021167580929941521780181306317659825769106559278029776*z1*z5+217583590846485138210472438152979576182256445854471348404227519270293912761887153050577011629509914806535504237884376*z3*z5+120334023355262415660699422312272657548982632977693406529553887529491839869949355528940501105036270775386907298268700*z4*z5+221325565117577973129900575640766414960454183459058029846227661757428951898164754941292928480575101892683765254437976*z1*z6-718745888244357195985760592995914409965045938367546416792172731334342222121550473969342144537897434106286930284201176*z3*z6+679217929294773017042888709323711250086070098117877501064751558306824799795562820964927528353353838662173142778572376*z4*z6+5766489465432691937774032602970086117601854272130564507021338128339726641804419310192855303151344994600552120951411200*z1*z9-10358187466010156005063257924431444558881908899341670267802145542369765918901281756229783435380365710565397482736763200*z3*z9+4628346915664606165715816905186307809324183852642989047212073078917782269045600119299241689274615738768368048033633600*z4*z9+121579409083181473715715313408805945759602070188157526400867647111981075715765930974569961096221890237059590489310878400*z1*z10+783731340434663174678271747763005819512708668932907237381763636988717300787541965141507022194940284522726874033546841150*z3*z10-967863764665113061051686037385964819732003573464611503559900993576572655370659883590658933908971445510830475561055283600*z4*z10+719809486889419645739373089532701463456850085560643208027218942443870159732957285448827329920895999480221367658791600*z1+4014502711123770652862961505629783392041872927890736185565727486944417963954921649620930477679401741200640832320410479*z3-4202445670043173447574967773216752324727184527340135268624539800036138075494098412571830487255533490984654385272082152*z4, 14940903804239915432737296974733891611988770304046728845631445700631809147507295267719814535186287938702731072386826923406965103696098727057957786998541265985150033679666858323755520*z1*z2*z3-1063733540061002893187700865978722231999079918532517583407251131772627026236607981381734684526982461903394879958362649465412091503190095380935862780863435876159563452158544725764157928186600*z5*z10^2-1989359570652680174117112976330779517307194438415125240439892876157954907598905781197096676733079641445656890528016125937447669526657948472306038536892299484726668578539120075430981625027350*z6*z10^2-5151248078311981743900018808469518955749985813731795896782194735168997245049603993207613700510418959947038942690625595047772726530165248779102876071690956400365757557671547059736357305815000*z9*z10^2-5541279627623572509630226831391390912534499775114139358530085356459766803588985676188088236440371477433531091832339016691862015382828542815640618019413895559258239317142408770832985940709671875*z10^3-621473388455929237750899414698373371797315987615199440277006665063454052098900139589919107655156899729894598273078824675573378657335000093859395731949637604241021212596187422007466544*z2^2-14940903804239915432737296974733891611988770304046728845631445700631809147507295267719814535186287938702731072386826923406965103696098727057957786998541265985150033679666858323755520*z1*z3+702428306342655559466214329296820645955338971997230509516605761936726288811982383209675177893280697337656102158013497517235707408832875921105111907590907559986980709073067021960853490*z4^2+2152402836849684318993274308975945961724484950559222250311826803856314462300161975597538708389037049553418340898334874545957495518378931521476129227234750286037989403983507995020913144*z2*z5+752153087884785122068713017407477727347889445522899526536273153983091358417179189857116603741212558681132013017428554473555765462866934860401629142984403212091957369026432645835734970*z5^2-2891442307784573534258437654708587107256714997682030024853859166812088573161806783888811036402176199874067814365817410786473414098622605670222722696757854540306321941789348572643505152*z2*z6-1185667704456502384704011365258157023435317345755849680828826962006771629959796344605020393339657011615520405588261854457352622426012367424368589196468705797561753554500448008855929632*z5*z6-983515883293168339343778314740497271358205522333452622439577507813413928051142599889068392120818047738464603678926355507341895755046819121054605104170856027479884935470517730405136498*z6^2-7278962634624650122659232768713828294685850827441186411130313088223787098695297560354110313257642557406826551980338827633185530450480691865570928914979646900837496228747174203760401664*z2*z9-6753289078997876502417716135251007428301753875301997023365828623674346013506249783381065742879968227207614465800140497495820299059883292484120203776120547794979681591089593134776961664*z5*z9-13699295083450219230218170111646142904244341841416369491103585668473570250411731937180597189507965281432867193979851798117244474131356442310502813847229539958461699584420240307358366336*z6*z9-221228275567763368991752041795743250173948761313629727451200985495550003409833047026399392051968996153601817166281745787605434923892732707480695400584303435522272827428545249280000*z9^2+42757750911010575520402324500724186884764812463971142426527357236149341957739614787077350283583076498975559077811989818883136850551498512806288566359239987619113924182330330458348026082464*z2*z10-6224485282294450551756906320591535867430593542576339854532523235601133660287062871351961518589966796201025518467336738764900565611328592826151434899135639800505972765469883789141604462212*z5*z10-30742118876268066010091139445902154027285971202543764526448303856795712420157014898154119641463016690577279072721266558796162508265985326956578195558779818458774410645937170658223740280968*z6*z10-68989679051411117474001092844586236859199323344636731757262416269117506185682430546637404517075218108563474159493267919214446518180075790477492098633678452530159807538436312985073814650800*z9*z10-56438959871735314582413014305585129204410618514611076753495403603906671757539645848926770475744825423869292464041624605059552203551106415871911758149021989062738971294496211851694283825168250*z10^2+191226868025399030379022866143743807802388275064540067548822885407985633418241096039503876018716993932595635087290517820842772970957745888506181621627549603034441314033551305420373158720*z2-8053552234277561154803510697829324005487268990586915938574210341024596276545109539426937229850666168051454703017825040183760779996001608829268954923713137220524553706320737406825751572*z5-95564831057678841129606748895366741424627889928754817624408504437765800583857266113283570245212790701124132582360816921537452196126971826867895861734872416161595137252111710033638759890*z6-214365669352899133013886037424458894026194448734478320572810993561735588266639719949063351615590991444155701755119186542563914932349196800133817954440229491546412370478586838175635725912*z9-94672061742957160851312826774242792993961442977607655678254867439881215310798250335857529409297151892159606837715978909052152746394221373498548419714393101914244837997722721258906281275415*z10+353300711153384824616956044118698295017926969853035933865926491443528975474273749571388527545624394047324718551316776188812361034952751487963778616355610911336354174271403348514234481202, -4*z2^3-8*z2^2-4*z2*z5+4*z2*z6+z5*z6-4*z2, 37766570454606102905199880405289418839960462118461777355313638028001597556069350248102323960479890192176920444331600*z1*z2^2+139406033309496022444594942825909539464376198254663578430683462487018780014932880354577458825688204879011682155110893250*z4*z5*z10-32776691922357094158130305854464734689435250696222332932115253790262348223451896940618205846304303627018321080884790400*z1*z6*z10-41838468926423264236545183767636758191482389127407569683378967693677282982832350854085889890105982989512754498597117000*z3*z6*z10+134291023217922925937220318184994309726297100212183570715862841019274573635671331988156524598691104588486611433288178700*z4*z6*z10+1328696405762697357709419608401335882762637454393392901720645385750831531691812368230722492428028181793851785195762720000*z1*z9*z10-2378913023522703019866090207235334962767982597874546584167922562012873018003332381512681019508742051135600334695234026400*z3*z9*z10+1058886862254062065248509535157590959575245628022694949743600011106530773720445443870499930659435859432606021968683780000*z4*z9*z10-11714069628158765941336980106080902024217164790322881812145984705226678563358977178038798762405804038212802934763743750000*z1*z10^2+62014768052298858577252573140981511396273000176492367669126215523212089958426801111853105379349391511484661594308697734375*z3*z10^2-98526482473393519796932085760887195222396359996003049810321992360428468631964095228674024474926055953374885659529338540000*z4*z10^2-259062940691949138583128690602843420914834432652468985125553625033861911840114236094480439704408838289401451703135600*z1*z2+1321268876078154088346653164714913911414855565833667168087898692635347197902388250900885297400812331557934691797162296*z2*z3-839889309793605898909858580062659589800966658754034393522697864173346311384351326324129897361783697244133763439335048*z2*z4+307720574994959871559452645683144174120567499977396746607337070010946356701405278379485404061108760132744535177801624*z1*z5+209630493144866937015688721300796481311553167678692081334823717884091099532514410974434254785144765331008538855214524*z3*z5+119699267685128202832460381886812123932909908694972182037494549754226392117526015624079338201345653924199368558877550*z4*z5+203962867138232363082112021945484367619497857163963857917669370723187496218108549977151870228444290035418627687369324*z1*z6-735258021333684695082122482040948735907173585735501256594960145339265367563768692914320463387889279455964644840757724*z3*z6+711491799449266889783825974678525178732730128933098524258842190295196419611173292056845685445840552458454930574206524*z4*z6+6041469686293116989537098025394444049158219400988801601085423924865149795304090141357861557424135881269915781811308800*z1*z9-10774821074252441339105020387993205069269399991498506641498394739658386213573630583002530664472379461376164672759856800*z3*z9+4772045426679521849195316697706764471054013087289702256068162391647174633375869432853571599417359031263223084692426400*z4*z9+110025229688185708677475681333334413437364378881606327533592598835128109728021619194325879051695162197186328144818831600*z1*z10+801180828227073849238412070280542007610266815584037448078535076122340703130272228676193867697708987297228477004507476350*z3*z10-1023012630258090308131358904159409563768360449226066340702950041328891435848178597649141977304563755120722136455439216400*z4*z10+764816034661852180926459769989872253895461195012529148356537451864440695226311018021279315853131651991728776163990000*z1+4040366329626941594037013007863393691863104293807244687632869631473926349870312983976204418738352235092690365797687271*z3-4352073356905118539181656425311043391096293659709014573617881137682136906686055757050693511070692011223501384257825648*z4, 46437031471389480135716847151596887243867986360296716719221760909211437634140563598993317063803621259530350836436586737933958858071083591402997405855269791494300073313920420605105342823045075313093017886197244854286220282568671875*z10^4+38776038940480705516168793315383105950500532169532437787179470934895037160756680566105435586295705467590391521208907568564634178179496868461169421006663212342714798104015581146043463249106148012037981725857823003331989964200*z5*z10^2+45085348843351963816688521424460231748142030235224989024942246066494368972964587473349722335846861131701749273656360743253337693880930955344707874981045926319867822296092870695893753027751606568813926594652993054443985701200*z6*z10^2-797881571343183588593720608011390401896319441593222578408688939917065120410304232707254154373689293053995355883653523613155428814854309558248089093977818378418190978152407464547973755824708580974754854480915332281882937720000*z9*z10^2+1364619125538958843700369030252247345944552910546940719092003559325448084192284774491782232415182733194251251625677583314619858291968206919478741934830184307029883077380967480791991356060918282033711769620520817084858353260793750*z10^3+8297679534880895147305653173423926934835309735358121169800873359538171549198719283784509909862641313045574222522561298180543364660341049073850514575540554254316465823268384986908924392099889323123335883699228470302848*z2^2+67571834051273723095514645680925469111138081883267271521733835898621331677387989103398528390568606652446384510037936175806664451625847150521871672715574071660359655611831931095568352970949530890848956449479782718771020*z4^2-56761309161766012443643309161891460490606361461911028365107180358181365598785752440043452159515716449719050327484136588145989089543997370260050226188534432361431899599556706061381895483117700194785751524114193528507808*z2*z5+66206651988283195826732750319227036912085628653249791349206800980689798433739498988630208113545181738487619987878060971597835967203316692989816369508805614466024340065280453521661050975840750870855378371336343730466700*z5^2+85814091965098340640754852190469291766108891515210906489044030987840581758464865268270134637528333207921889698458698388393106568620943978653702844678239573990267168497295610126450483521277761845212032631341174841176064*z2*z6+31105609356095636375151765283823153694319973945620156530819277395685806008206141727837873206887785632914441386114640410971935904628812601490379141407821969642568130140444814746907601828701340477285428891152025559295744*z5*z6-59359021800275998269137996984517630752730057875181615344648512101998668571286134846460751605846413603724008555496301319531157824658046684437414694098723291121180803131240892088129795132241320657049916516969088651377484*z6^2+173414497575964831368870838519785371420894829850495290619041180561275798001293951904307639649957355214053708709020263440144321983968114571519210214359804832619331861404268104487699250013944381570663543669469293698869248*z2*z9+142562898176580787570519820707664123409031006806604756332731055101235399256246241527062259151624807830507115306944008877159133086389668517135143288630220982112183844074054241086564789548140275298724886803282300036994048*z5*z9+292389732181219677158394765526095781295287688397503072431207569245219271526510119967673562832393895963126762234213671343660583750958646859604762142355883093396478606950678856654272663004614100150561203009329272551068672*z6*z9+4793831571394635072170304332609272113277661080831649596304145155609688059493525692233891385630986768601180540277584213244432566319163924424101071592544015028583791798327860745996188206189527049775442158669660160000*z9^2-1160188713339067995515138381255451864600283483874783330931191935900859301391052058880870774693898554890771346972854391922735625483157862033982396873484808972097203314379078694934423682053771715758164986786654509725235444288*z2*z10+222282444315921259704824255633674490763469215149603364945111026581611245883122616085778193536815600912768228396468578855973892324212404282596409820446005401325454894623687113969302070683076054465613339667256452034867389744*z5*z10+728854326917331483366734896919182052649387106951754880347694564865649302533881783461816954022272306734634336733233028357306170073901221779256038886306648533604088285014982872739314735141498219295400256244519505539388296256*z6*z10-6343600803318553687995472561367380434125693956510714686725079121083363308451176069596188014950528182303120969359103126778273113877565537737833120095200421789690245388239390482832835536157229492504439142291999309907227222400*z9*z10+14188209833218296962244347542432032687970862685399351865565387160817543904491650872226951651198529673195193644134486877509007649717386719921722744601141812649616612984296268761079090290425876332760763398049220592796289286136500*z10^2-5067366739360637552739176687856968739829606550869294076248860180282492849682599514748983920403662221715846719488802921580999821800264230102687749656155391966788671024474496925960789996100199096574281335337159080414699200*z2+269086468145954803010555332494053871246616113387646289334746827805945033040238226750269118236166224795752226966606048315363566106214473073005235212758306793136159645212793814896837095419456357036799412137758764177795464*z5+2281686180147647867531713289659307116250417865401374682081824345277683794833291172156189819047945602486213814525368892040980308610503344390455778890917220865119169657334728455659651793797341771044309248566214945106281360*z6-12226411334322265382302782385036295802759097697529477964710590912477029813414495376329990398388056276178659053542816504376754963101144368364193500934410345064459782778086420265639588611260323127994698164986402469243695296*z9+68133547024747592931051156432390652503715379667764261905832898328333417266074702684509328593059932144183537381177109577804425495127973882722964054089696373152453280675940807713345602369805624265342823289757858478623289928490*z10+139788716314922411102372584438996758411490167342044462559330340624056309269240115040984642633720673388847264974647951163006737338262011729430170186018657561336450142311710084647290549869031600258326146508781104394941802901, -5145966807087758959163608815211386130764931080672344413812148931192950379601053905990168055545423757208222133879325215379974614267400214647708483400437522214001564944724126069394067343750*z9*z10^3-65889516309459917517697054679577352023484491260658625948506462288742878981890565565777510751532624042290973627850870216786637144709965884951324006347564303439179187168774704653571600*z5*z10^2-132417066321132561707874334453489970227876044069903367548472484956869275575581515434966358381539092079057636148358332082807340513650953887149801049613606646667309836058447816765606350*z6*z10^2-66444979792834057908718940566381009051071667142859213433777140258566185626227542382613645271601735926479655296449969582132283482126959342905725225018453519615324298100265106695803515000*z9*z10^2-430416936946445897278916054097804156100020812938799484464606222186971951604194304000640405537695907687648681531076266709330566523778359986221285272601911868116156340702348743241415281250*z10^3-29453033018463358952489069448764276180263326081502050922333996401356704096648416775532138467988420710358606008192126042029954783488662392996840288409635127195030142341806486384*z2^2+55425168388060359757290889934418182962473979558720669910205785721504115683648029083518896694140221473693888098624211183874932854218833847909518668096133595382487437039164961550*z4^2+22070762957051438400332662095336285509613829368433360109262460791944433965579494803991947552975779333398285161031138262084897540792270730024791691102512649235050125749624204664*z2*z5+60262648989428050976339910958321251023346505588043765111942826747043393499631031150658189439019614267736726253463329188759797445766235408331252731838404124540808402576296924150*z5^2-48661066310803748386298155948190780063770991690516426770366140952168667303705538122875227069092585623547076727292933207820648438676310489086871167579404624163579615616407739392*z2*z6-21692435866713480629356235056474364472986706718306668200684418803175840092985224129978766366011659739892068438650890338136116817116899299497452574143644413471476332132074488992*z5*z6-73187214724423988172894613456956093612376621084013195479804525582033900905457323110377696796785606870957330279816634109853180958565154806775663344330743116851020618010520033678*z6^2-517539960168933214636152994156889717756602176102161907476865650106290952162196154566396676434076432485936727500227705339712267018879562695775797162811807412773176968206597884224*z2*z9-162002340933873007907351118549288404979328758846269279259192156921333839973990131689707364118289629556574305915074032740083950543782889739535786738305634646620349529042585203104*z5*z9-411713142978480985999359682073325684131498926613870933699612916142393231353460410148128324069988298498617308654361821198964730211869092513566579251188578614491167048936009887136*z6*z9-7695358591439484701683112577230986243178897294939119808256990149167822145241943126064387644369115035061542421307681051993293479799243027801366449774397913959020821319680000*z9^2+2490467986285156952482416954262316101702168020736038763261372873634179874497997255441492286850951326997005968440067463329630952444931569042571890013397706181698868701620647156124544*z2*z10-374622112300527348806410195767167955487352966949973046557993865955741879687937687117977249825122616683045085586923671796735104804342901890515616824846171200174871166887276350084372*z5*z10-1979268085061024947290208190147802159269006546837948824986359036071454430635323763132471749280658784053144434458140437564675953183439295211929084201732725178288757535582120863613928*z6*z10-291269081195326840605940122801996914478019290139162914845181633915588312094078075392310719083419651359134522711719533591465354082405296685984215432322507793503327442159969265791063550*z9*z10-4307515265225449002152153280813672368601195050735731336425851428919198961618358564724745103458987941998803988658352231075818537439589880709390968610760108683282780363016260215818691625*z10^2+10689905752135096550960486262478462762789751232493505704858673570865947865542966137563822800040877188490450913673326707262348531293628433243555302767972284417448305649212262003680*z2-419783405400105294713730943436417794526911474354235655755503671051810765656527785860850596940723303299383911982182249947999584009923831070679749847983176066211820074523639225452*z5-5988602638580862345504238600660340415487662584613664716526676785195251827042340481815604743663116942002595824260407854844566787281311074024055000890516818099043216360806669516330*z6-434153329041093112204415880925942432620325473792666016880638915094955974703919978993145660595668367059016283562180713010011969211034551140892700829441152641881984569721310897627052*z9-6521501054007045344908459640781883561530479485387707355358609270416302544748398344657357524548690429326339776360229678069751019390397329024938730244217673451679145016132306871091820*z10+30008913130756889268388599869956022871486415538347094587338660580881983310250332080018049902250060624265989504864539809952107020904648839870595476151120328835582242235508179477297, -45741927174113412970343189468545654495688276272643061456107990499492892263120479164357049382625988952961974523371779692266441015710224130201853185781666864124458355064214453950169487500*z6*z10^3+391754821252188456410784965667895211427104164049164102416486709103474845247139684870756544960066630959430074865629557719925110099113108401274842996450770531778036368660415654417133600*z5*z10^2-102703618213568323740140820058590366866815354693202804701769173845756419238436525022614282957050411869670770968121961470439852430369335165099053610725703103673585502386835448007681400*z6*z10^2-10454753937408278831254732704281108032322704007116526073752927344166918104025337493448760585644259271997702188194921355456633741162727155204019435626440557388446595066577821682351485000*z9*z10^2+4626276327659264989150334540552879827073755924827747596805539600165290810118554447135774746231524678249585107958440378473134667834980785340433428456846593454772738767290568894137535887500*z10^3+120837206289988000698384855760353430641074528029252170514629053148580583766783268909249225713705806768421099671767717482031678163609535399171145140331537790648460512122879955184*z2^2+268468010074395910305614694276093636875690736211520614025966289748473139961484671940967431158007719647501538161695875986923371800405429008953564307328535756713694189853181177350*z4^2-577743177324419694511723188428486307474904332458068217142618014886567745799709450021332489381431536712811914014623197169381574340258216368162440713106803063673986160877161061824*z2*z5+248043704124967554276801740726066021637293679078346506713354322288725871403746723106299209517355009355156503097825080459516629666580999219210188731213192403592433699475467162030*z5^2+872655593011465385451538547200849118581566536383720020107247256742735880033080366000667426457117831241722621215027222609351575661481095031097163961330088530760144236255801126912*z2*z6+331973527167552038273145383723661195145933314931398088644248395724486193291340987067083091518108055667774204596309316643308921821918868368839371209780402650227566994658680386112*z5*z6-156308687713182200833262690441826632154610602885747090675497391592965823566550203938704464336024806832809618368464093972049119012583036909477254329778797890051494916452842829062*z6^2+1997014081040702517363780087662746054740759818675159301412368006206506671247891978976277851276649909608252756203790252486814340701073615281423964548828871571396466755250865016064*z2*z9+1683697089824131813058556243825991793526150765177172957385874519279253261649851644120551811365626462288340445818379534697870164417697250670203206237436258555730039461259039556224*z5*z9+3443364842033021376381281002677180342797222435911948786826372517213539510273905173594223360873444868952121102161623881693979420024706391857357667691041144340484006238050395591296*z6*z9+56268549807915506318093610935250206871252293621026256175403398447379455259941236672819338790886448387691363050995461285661627896032240843196594610492213868098988194938880000*z9^2-15516453718173173435680501023271784203483228073435417012731125059656856532792405115660379324458760485085431757021166832145063437421594902192498994364459080176717658790130233290464384*z2*z10+1982210757405064362050994197125996366475818875802958032285948122780091271293812751439687166905310043340651257432998153333827367570167436421520129897347975741835657224804822434318092*z5*z10+6380872975675583988968303845330038583091661071854468707547843386051791036066180014231307859007237202476377685851255458482871742002097529532648429977587311020935894440459073343307008*z6*z10-84888134953109319316207611049386741188845290772087798914870029541838914097804051491629081224690320559536821549472980400865847811769984655049892485114197134269508480419426473117293200*z9*z10+67048011033086772809642634563835436933089064350761145963986608375318667132904253894030908467377589912537148351797473713119555168985199125507471783876416859388086471412744539274840078125*z10^2-68159540921583806890157713493912234043648744382787170033131693360925064315668304256806296358298766145028122320214628741389620561885280254156578618045412317213589222150253098886560*z2+1602372532377017662947740875873109418152276345525307283649358732507399878579315568264909442838114719026036107330944631825736956800021191051672055806594475309739155651501429815252*z5+25679575371760598472217231071224385195501022615013102800515142621048656541845712608078535092945386767745068515051922622309086481488872614683592138258014864696136281070160748898340*z6-168343020784297046955510007308577410773363026387261593344564017117416200437360709034355117477592607154277883533071016325464326591999239460034463942832159343512557571117912743158728*z9+345487470171861792547047118277473572880043858689173754254530855861186086129057773537194110402865844549230985356551139695555200272053123692068437656183398206760382830262770512540051970*z10+681585090605741115296016656031156880124403417571064312379165577305218602406574713709913430603676401348599332626710758599099197685017642777447161008400958711355199653873819799736423, 437721791139841272443475497306656980819983505001369009149358760760697533618377791046478941460535779454181574386332820021688430772346642394276107040972888651908692392958989989953775000*z5*z10^3+8748512548690140549163306848753891966140938943346445935690505256997865418098534113614717322111512001853809851481561896335765669118672295779258771007953470242814276882302006600972600*z5*z10^2+3184026059417743588056036037016448319490315860638490624538358197493952595542572504783194600974889048210937748265336732761861675828069203229457087729927026723668243006970468023326850*z6*z10^2-4165110978048893458384688402392906422250440094378392848824893477561983722796558208333190180826757177245720212416596842951852118228602404986774978665430956690064780877037072908585000*z9*z10^2+19750540929994817358692978205581292842176948183124700387703180777067477762749182695755191278323463124844592920437910647420853032457995398549029404258898122915935172966429712907360615625*z10^3+1510290323816046958098228115491108069564062934802455735717624176264028032325633617269369133090233120728941671238835749274441944820906142915632556648216669273738273171243491984*z2^2+917146683954727390114945269471328151739709516249745017448367845574757127835719747601838540538686574856103242913209032175983031484244544855554275305844419667380695867441872650*z4^2-5196342087774940733202424070559576341054890845891740327018278491109370622745903106036367635106254254475411215305099595025221420619713420521845915644103095658566655307914910184*z2*z5+818380296611299192748292358344980059669405092870573940777455976762574584964942974342532889069404955622809530596958058910819752934846824666725093080646933200073846248041985330*z5^2+6668203408507328172461604005384265452027190026591636442681910991729879174517504004818244167180544971707124358870654524191918835126229952444798384809965411317663955312781939712*z2*z6+2684467691471947033232779669581669830281193353148603228831101702992365754570516331475117420522799409978464602754470900639710608247248958842320330082044234527649775069794009952*z5*z6-565073577666735817413714453920117357141992343270434700592708162883521039765734222837956753849777973375219821253312158572052628342169680880712852583398449476764708896621555082*z6^2+13163540297498518553971532911685339908210923864229221206174818937255246795298158981563788037331902452225889877192064754312231536206749762770758877981689286192033835496342002944*z2*z9+11892164805895702502451662676561506536048916060177932771721290111802994226850865744473984738363193023119986640679379521813669732102172595822538002135735525319012721614746241664*z5*z9+24186462017579685680817308266941204504594373898486294814216968928490328752710246610511521388048812387088316561698922114317782278505922118462287897620003000921790663098579532416*z6*z9+391803767437378915132820681352128141742217155874490202478105610391682300080896845379224522968493488035009407424878542794434678432730959024363169383321898234385900257280000*z9^2-60610233152497380939337368950690985806672762626970634213428539301106131770108562091646509322393946193316745277770589351260961391128671736078255702461046196403095688385776124379264*z2*z10+45767722100194123127866906154445557402587484005605444913671128483707333288702518273397949818757104598994484472607774367285651459610403149925764415747145357881366439614566602934132*z5*z10+45951657515863479138639462746920519366874568440384955490078489295613746984833763226496498757826968076292632586194399909400990546382084423580941615837603040501709865569132457340568*z6*z10+8487984060375670422867292395879113826027996425455082646968876460680569806968012433906297473404284588376928266303616478658335479560040781461952950757498735192378877904194140730800*z9*z10+282915158042083523085200101013457121224304093564901675918283974312372675248107254251530329243315654497498486750993211265515891008901219816912452515666540512597317699525132705612566750*z10^2-263465476381794335640947169183264193122500237267278322631569701875115604817001212989929251037274551503544356236550377768651411455512781635656779353799208517559352332941493748320*z2+71885095623669882589868769685163730017999606849097469673745810260069686957895578085532985879346390782500195869402514431137838821883974411682362641875219814254673866107173871292*z5+137411144005156495183628477744130022856689686572994962639289240004805905155639993482856502117647750779669369376240584459610154885323471742635512684367397676597961243359324160950*z6+136835192075080618269186929055003355856507013367326632498189699150187728755782098757885732595339147668535445766392319280093825795795459068363324859956987459560426357060282420312*z9+1426502474397563728560270714834964448553270547320877944562185786235023530117218442553226829269397589776087538691778728148644477227348847700497910870337325301601429328082687770364645*z10+2710221961533363693264327879687932273309375012820531436822909679517608793465547390931937562590931868475116996383900017217082981124007586911695300063504082362096635716869601390138, -38664411656898027679735218187112041508163584667106146015409102094557916785468717691891194052759111331667501451457389521875*z4*z10^3+212386713654940133768005032137734882083274128350488127403134857619029395537186494149547879191029033036678847833867825*z4*z5*z10-206017385338503697220831556871247034516853312671335680361722358036385410216798824549160534941495316347499515886433120*z1*z6*z10-232819027770259373882641688545628066232259345894750049835136838250899161405429711588675705663686817896398889774285000*z3*z6*z10+302928680344401518614250475297623666088576708802325562267818412782227120977279193755075842291752745289001839503238870*z4*z6*z10+3506289631396200227740268135529192400509232952245916590394917716650868136579113511585325227016876497762250090891808000*z1*z9*z10-6874104116364425439876367375692865632824394781606677431645642092457523922120283034101100621116623736199557861508292320*z3*z9*z10+3408074272933057162556116720202046252013090426542955068800195534920263455512710734774890068834933004720186721482380000*z4*z9*z10-277420784843639561471491917474240280095870276700601602230365972072856775023169827802152614842771398882366984595918078125*z1*z10^2+360254913981173053506509770777216005186830568490141720045921507692431921145807416533333091193689314383977498885398350000*z3*z10^2-1184759294881925227193461832650607210565875856708091483408001903074303363115167778345626989599810456342583140989529077500*z4*z10^2-587761536196062694738390424348808598006064408407031088028959031447693961134530346836906263076357329595887514459720*z1*z2+677609055911423331248543631291902752717599862229150455943665591917679457256740042557688379471511540728108762297788*z2*z3+247749693690869940073385102745277218152834625637250947582919798485369531991506891983629604251893284746556797904716*z2*z4+255977979638301765639095007891229019102510449614088680199740727037810483648905686378274004910977478114881391508772*z1*z5+58541231242967240370213660392188143504531615944991134667098245580498085339230331269255518934041676303488004257142*z3*z5+602756489360129576520001397840073096148869314207466791890711298045490658729860678560743837303688352774024376519095*z4*z5-888410537801705576585162332180136055119803376151990501596430312104207981498940350291608817775441459526832496386698*z1*z6-1890248761129484729796473295975464466418681822806019243106368234695779080715799931090966373113912759982608144602422*z3*z6+2074163669762904841478728398224957037986071122978562134852842908785633157756623512404605298305244369231513238776502*z4*z6+16175508741809622861334173797458834990875186531597316525734492199820817314519224859799292209631426888267859478278400*z1*z9-31439209713061375527706205955954758178573004346216609620729466543560319917379242310989116510824906238293449382262240*z3*z9+15443377122102008877680751956368257520598331655448740569604830809528563457600815529050357624384766344827912297969120*z4*z9-1422749888627185465518390724926573159975162149360190622590014628989172656358119687792853832147876388009790057737245770*z1*z10+1146579550768028384019637171271924060875287043450838109243343556760692559408827047397923750353261079287511769107918980*z3*z10-6278475855615426980791194055532617694057574653202780935134276846814953808501404819244878349471870970546414274577276055*z4*z10+276853007717607921570519257305264686910180449694019497745287183936641736989802457628106717396694785775348513185875*z1+460281097061199174685907749243336399466115126247715797763949945805443295577421841279273956851259665770308287763848*z3-11687964603961059152908175673179972380687655320231097515564222015060683179194275195078801844007995650076535188998034*z4, -51594544771619627095060086424488988414372460310216045361523776639256523608265829065934296664159197557904841694449585747694089969178160091791852793988823558515625*z3*z10^3+187801724269285668875303080875721320824682495832256338955245770449634662876662727232930718681119145968784903915352709487071832513853368674802957703571934800*z4*z5*z10-121863272682150642791370894891167245044448099609606895142092886692122019448957259014013087428498600922421289515126350291850748400576813254076805892001382400*z1*z6*z10-137067887387412391763323124974176055172856505440291419437614188450483155330924065669504951705935255321912776030856703742359904505161995084146441922570651600*z3*z6*z10+231358115729106770248528414784963216783140338452339649689050771061620500941064755788608112867810289621240352260982728553345196921819579304130839918263209600*z4*z6*z10+2095585126280398768949286634664135210120364447314694990620871934259713332106693904477675187762564722349138292306721106619587463907249571317486342221683360000*z1*z9*z10-4753879745935096880792317744333240189012469116572937987138520695291403045933116536876154931283639321499647047150223321977788516371659254302463182754846672800*z3*z9*z10+2687577323921971832512720986808190638840676551581417263267438719761264093284157478595666806365260360668080581772110693775290794799558117565097339011060900000*z4*z9*z10-137159405612081220313295122716036888326800837761926954742222412947435107230037759076541103270670468168116963723931462246743012980047934135123232657420189437500*z1*z10^2-735493231501165050338445322315638527502867707337514405840024672922937943913991242498079205400542888708588656223390405872795694625851967595196946192992298418750*z3*z10^2-196659780909782501670066405043559703997016600087329169181517226034755002026420840558105570648257348136399119699780836763496097033537069055561320051066196632500*z4*z10^2-482464665032883034312620171323719597059887538891701832322084723017287852687411609390010008058109140453894414822581300643554772123342377537088298248480000*z1*z2+1088808715277283917423992765667816825437301798298605651096929159590460661830366980516128947729398825527271079402220043891862386147789955834881916071567488*z2*z3-391257098808074108075358357053077200869461817332976455379797285541276545453455858099511510885401526440791976011403172648561408901521379289135180429535744*z2*z4+286051374379978887992342887022896262672050726713404568794691553050963011294006570571653235171420904893172153543268631493664657882634755511263794629446672*z1*z5+154319530847951977099014204872074523097125796757011003097295869413956324794890980937478660925262187552883706992365905971116111149910266516963817885817072*z3*z5+377066989911165618526756187576305531631922595407155126320207240374630630104942671049539625363722496443538359951063500647846766121166788219614579256957200*z4*z5-320126900630843718358302711739338979649964609504845129352752853720814051901467026261738958544307305578978904422627837226289056852522574119196149053337728*z1*z6-1334255655653895093913898379781721356960462954514667023926277451865307386645368412079653685671166756641878124376109530889631187767755176711361848466059072*z3*z6+1467954757714540037456323082465366313823462598613214463189648310628492161175391654323262720852919891134947243970924676547298688740371764232599603078207872*z4*z6+9736788651236164903262459712260131444783617056409899224794451916946305395031317181378045450462062297171497963543107656581155973916411767063968128775865600*z1*z9-21766466225759229719021618055157206689681007544460687582854272505558513230744760761298686412133677162882207724016408253955117845566668314827794888028727200*z3*z9+12160362506704460763106318447792090656052562757201492380413357370040351053415931212436990283321441463231994059703585209892450957473068208316991076025072800*z4*z9-600767555430705575226698207689150465427914492599310246893134294650814125436727120038902757901249462657866709549715305195477349726137952199667503664652055400*z1*z10-4829882234879504722708536967022679857570283912687961271550812699309037898190801213679869300004230872031538256284112795930767792998520258976644578920097867025*z3*z10-361891019096016870029209221155108412337775927695035408657338533174999110359496554264276164942317094319227737646119800586894053130153714832913853429622500600*z4*z10+598993284123330729203766102407273096866471196213988550444026749673027545555355365715664023454316757508126334289451653996044607130761059674307364230231700*z1-9255882299043535155596312898312863707720146832918540964647072670121007664917630905556592191831192125116989108678553246655954028634665928973699019676044012*z3-626510716458273054845608280868611993004098338258693559574742612434336008453019622476078211642935537263820641956809149023251616559467338540654187584318244*z4, -2253701310169116931139319635108103502928203438810547077436720087379364207732659679429076012587137908526841390055252355045025543943671210969559921894225801859521015625*z1*z10^3+7817882365742796428141768028536015889123667207959735001849087072821424485936586695423121910350948145426415788545051808271302117734204174810291436808144596659950*z4*z5*z10-14002278965198751669577427884507203303599158456061949666063490176052726971160875056613758221606832527658155063398408600075087840308663302006110159759556408389600*z1*z6*z10-15720821752022547416523887262206861358390064528583705600523927326940130834319568387617007209287596446405266210148858439327167022724650750353159593689922224054000*z3*z6*z10+15788393301174233334145438328580451035773195031982660399152044354361086567127800709279949325549578293076524667848939780988728624811107068044073171369549782511700*z4*z6*z10+205143755485899578839676250194520551816004578655857090828564807748130917677117055432920018326234667295249009433098920637214095154570559451367992191050804859520000*z1*z9*z10-376370387077940602348360753586036609612872971956661416793654810044688748007142063861454001271474569868604472015176918729541474926673811587674499081609233857681600*z3*z9*z10+173344409298149263861604947963244680494898250319960410891022850129999726242959367824607382349901733785695666513124308423015340956926313890978343561085137105400000*z4*z9*z10-53717881300322055750874232198973546052715473072523663849445094526228375126482453223376421941332581116684330150655177724920733659950772187248344121218396571069340625*z1*z10^2+42312613676054313508483006436185479508150643553114559517740043228427332965152519909902504074780322746925278405871120822267376189211484833072588954868293201675171875*z3*z10^2-46314344101573513380649196795847056797883364429988500744908896518557882697270992110727000520497668009709155131653417446751120906488187500524982043123723336020361250*z4*z10^2-21027756864058977190636061728002758225694248859397133130753604052210538005091543038052185476770676860825184848757948120590729014221515147863833073941466199600*z1*z2-20898161426969297923853464888137690686242349099688942285245213594880884797314159388161609058365184662812298874102287546130371255998473244340395201442725884568*z2*z3+59978021951820814273766133604637755974429425487256899380660131952189956015741575803852663018540989293157898755047747655330906954593764719542796368985741316584*z2*z4+4375763889442856493537873939400546006264148160401271948234111148287295540101117738919186850838398611810588167142949119517254483615470660391850231772685481608*z1*z5-5496917488025808949409336677942021157829551481826278946079158738754809064517964373259109221173639611348457307458658882017936378790974836967926655030980867292*z3*z5+34515502087713872136899295375015117480503529573526328754975469758135606038908215404582694878456818279867972982499256072880582030905506620916671910931828406850*z4*z5-82088072859466482471788267576060142816572973218921259103437629562047726183425545785800161263640758506158883483352773056468242738517048056551404364428032463692*z1*z6-104200153063219241095887587632771779905750059960842948618595884460283539802644297422439339159842222148729609510615295318524401079654684827283309273670512550308*z3*z6+118888956050677682376353678681427224504289844189601380635757616420056613791993422076467836334200611236595832387322585873714546986070348050534330182486821857908*z4*z6+943278018749500491991638342498817362926528868733287196526328383133659962838757105727714957735639583997155302815242479175044210893398419719966675165029615385600*z1*z9-1719700784020295752646808976380995632085273054735719988204716591913683621699325551925827174500552482486415005504350236688737664029502614533242674612611383876800*z3*z9+785874213387954842429968139611267861141546838080124338678162121084715228050525595898759685225466914211589569913074015293652329649849926440470681251242590993600*z4*z9-278517050035733708211742898394537630414535456769886959442991707379360045536638725184368130143653544093262379634720395668654855138592649664784112582032450714717975*z1*z10+284402348868114569188301769881280966999549906716501728570519168264252769732022288756612239708624274180768844061155349071221371085373217698765679193896899970412150*z3*z10-333996547729237049984572926452491054936488725859079018295001110583519452417361801549114350830775079133548763344668429873983273746749030180401861949918496760693500*z4*z10-290482716735827473809716759860009198725019339622996991798839864611493470225031807356155557107649674841995745577678086278145358863397252021214403390053644900975*z1+515367712903356614404674754032391129224935989232916637788817751759709560789023481676149727254524122564881125249232603306389177366254935500984161925356227328907*z3-750709464048628324703240615051609639098659638559621944590264099448717181203076074015232316186664402072972703285485865023697357601522592004290684785726373588066*z4, 1593277191053694966313119954598147357310831995622606232177294104306317396896675713591816792082745367482463831245239375*z4*z9*z10^2+491539315344817322148693541854792358268224206639032426486201160242670305687079562909315651074541480932107715811290*z4*z5*z10-75807823402462961128648733708792651964258997477628680456103577607968830132541133340716429504965963112373642414448*z1*z6*z10-95263618677788356102392921292664256354511602759301904195411684808630590185659500273990506769616638084699268027360*z3*z6*z10+412616560303890461609666764746430644342837231551863173594955261275517029734408693228045782166992375194018226562478*z4*z6*z10+1614242809922551492571697188658171372913338908419591965133294152509259955952577740390416134187107436147304421484800*z1*z9*z10+1941733331954348224604817007435372771480077435117644862968651740963261530035383505305918399265988623986721722952127*z3*z9*z10+10637607028459399106322704296287948487505507918534443191734902978586333513127036123250432326099798367629418659207375*z4*z9*z10+66135521779356371323883299104412097394623569302607461563432671851229478890065020852559674845703811043152892790784375*z1*z10^2-119607664208892691270796724728944530652110186283382558152006337283199293728288270645008952104892062477234422382584375*z3*z10^2-335072924307116162641163997620350741063373308656394772672246008557618624900221342332343309227663509136035382441686900*z4*z10^2-1249960375989034893169814857608624049026312092090847227094650230837556057174911507631429403760663353726684717708*z1*z2+4570701904472509796104144633673444916056268355355704788798485009529196113472159266065255105593773279985683172180*z2*z3-3117786810455007257052447116065186903149421358451010304147898914696073139747859997694081603031005535952137439176*z2*z4+964209178424226846596072198591350269189179065875715632132315296963249102847128859481078684936351753794288848800*z1*z5+831809318711241434498911133861409926100802665884118690309266508850106383032049785676356560748963633584298838996*z3*z5+374081052919548709039754814263468702575154510807664273458639274632333887877416665099347516759893261391165191302*z4*z5+1013143518382338171081451957836434838941206202700087017805297096269738075706216553563950817197821121371109745502*z1*z6-2138054035557448562975560186924123083790548804423099967999494260659299305469040623259416803225391576543435864238*z3*z6+2136050052337266501222481849102309654712455028518054237946622040442959826966016774962717483095030939648882498654*z4*z6+6941486190372363012802288871233988639300259432962336882599569971370888890992238407843419173382363316074594855360*z1*z9+8915965352963769194055724633756882391423328102735851153260998159650277973518206790028742313304360237037361217119*z3*z9+15753095917962712881659220346610086927309739367229578601655160776975476281291699586589439266372715197224895815968*z4*z9+991992773935401280123733112276636073282995843265472211320202278085743880133334160826686058368369720925615698585342*z1*z10-2380170236087336176674631246014189579063775296129845226184161441543348227427127496382760922761956152760675869351838*z3*z10-1140544597336284256829220627989231324867039967068012155488571317032964143736464365023493280604886699874670289456692*z4*z10+2894456584168235411096398451995074544708623279876792408644040853286490798832593619085416132768436350762375755735*z1-2512678391505420796943128551661346582962149888218314933339264950731588521831415977556825416826782518710137109687*z3-4102295879193197729661977372318758058676135671868834532006422302686852305304947692335656263919460035177667712288*z4, 708123196023864429472497757599176603249258664721158325412130713025029954176300317151918574258997941103317258331217500*z3*z9*z10^2+182499822944967511865420101596266095514407406564647259234610933713945807037590111473004744412105855948001846382625*z4*z5*z10-48414780206913161080941115851202529314953151106442233653024429324344634187704855245577179410656840882644072840000*z1*z6*z10-54306088275873442643989108705453904004635244281467856134143473445494255179003217685183542751991584283090365846300*z3*z6*z10+181140301844579410406699960060216288921301496978771554374714674630471087140046479292897675981049782838004931386750*z4*z6*z10+720385605275906475636351586030513485808806646831639986387984018940669312897379672854118306249519502410529752880000*z1*z9*z10+8738734210605586191867646647004914055719772211212344870879282599719676202817692651428011404251430707601812676180900*z3*z9*z10-3164122902007760574165254202327683096754028866425548506631397827078929699886295386745521028529599520716174536627500*z4*z9*z10-50267454655004662112599099156478123793889210086468986079877072814690559203636318178382564079881047983754084083390625*z1*z10^2+41515905787422815400849352292859164052385797532170502532379941484395638406742919540023592540439835105958188324236250*z3*z10^2-68365324802193630690481667908972129076258233815286629650043449648909922841531541540262290948934526942579325566895625*z4*z10^2-409839624667687700184427046143087841135212040843256498133760629048654832831099171032835317667165833422164451600*z1*z2+1762597127799191214080565457075109120790203950566803075449799785924533442648072229714620513741058899402821817756*z2*z3-1298866645844847142634889980243898206708057059541026749266081250464567800858656459527461721557255396008766294028*z2*z4+391239649882744738033712690745722043599116209248362867493590658358462110964514860616186684445687893600257418414*z1*z5+358294615405365092104916195212306517513805272491292799715781244786611296355777472819737945416825434377981214664*z3*z5+58307791229744528289313520579409741011735305929443713755838985486401363076009434667432593742249364805569907275*z4*z5+243064891727052830945286498628896740717238967358195469281591594444332328969173773258854639105899557468758692414*z1*z6-896394475968350038908888377560121434432054297552014343448382989705752646545354468732866900668023017691032398014*z3*z6+984413804551311190205783511629097969756404035451073715015914444845440463410797871186413742978460150855132241214*z4*z6+2922500773972299970659550725032678602089249907230978849961218334074744627480435747537373087025387177727526377600*z1*z9+25252337466567032393871614157063347531361195535964748363659571383873864918989672790882317864362006269835009846600*z3*z9-14184891778409526741987525976888418373949784086149223399065588551999110619389937850653181408673965865577101113900*z4*z9-208138597998200197505399999414755001378374403138088998059782817649412379669861622161042791149053649646579679826250*z1*z10+206251238459484188348718458801823097352528070277944877582872319349675732140124770826939886620945728777863915680100*z3*z10-329751996748331705849147896182376056155095132328110882311775686579838888376544722228629314665925879567701147589450*z4*z10+116243235195788678243979483856816126773592374039270326948520743191106867310451824786756726218334149097244393575*z1+2290414599705837772761715179137761151929515438280387603493759032716397876741992911341581676674921993177407721406*z3-2378043438398017125377433538331840725127523668665357991857539283594038480840783742294783899845009713582573844453*z4, 21243695880715932884174932727975298097477759941634749762363921390750898625289009514557557227769938233099517749936525000*z1*z9*z10^2+10288449149682941245247223646210146343180067330610998743433092396321892866381315834312272758193286516101299157675675*z4*z5*z10-2202002396523519973573002760951641224552837866675203705945641254700191972020064741024200445341669419936163644812320*z1*z6*z10-2507277170036822849626011517764994916408231968113321993815979112116040095684012410166871832888561080628047883717700*z3*z6*z10+9387630250560525785555536247080787849765746444598476143304616394436906107546071236552421768887476682684486783347870*z4*z6*z10+224928085020652086350997346273192621725170248894079819775097251994969826852666829033505397610892725917634277640490000*z1*z9*z10+20110395346393494419967546314572011833929734867458329084125403951326280054569155111481048847907772703940553518545080*z3*z9*z10-55803099597521222799539430311326833230101689352074637403221431340104948185065367489581886006672523537303602838675000*z4*z9*z10-628392887146951374351804295255177897174763141427115574511455828258857419629492320768407941013746024382247513847240625*z1*z10^2-742736480334672763351251407096717784980167618255211024817165293289238497907787387867119434160703503483311221907562500*z3*z10^2-5745482173012612564940936286216992358765826103701217264405465617051777559618187473829817041879439243566928465591917375*z4*z10^2-24591955009865704817744896694032632233802996717070462684159095140217183250408003365331730750965522451527430533320*z1*z2+96657961811795473432135357100184156312205553837675521012626755609409565413593186106057852479262078755036429103628*z2*z3-68035300663991995127577564675932370706961612392028064360445899839932648235450550045497800312629486200821639787204*z2*z4+20985310411126464138302157282990259312194718569425144499057055499909211615207013808286057772345907394495525443722*z1*z5+18435972535887204283838246890746551878130321696044926367904115273726427958171315662279598297256899103834849793672*z3*z5+6019102440529925716538764397333468823503726705361253487344866043951706467006853975579195405145866172609812529705*z4*z5+16997408092533960908913461866716072390131062615210522711327469417413810685156267097060621156416785223614155424702*z1*z6-47548230798739894398146682869607151792796201983648865961361641981274696051055854403970241439482262700161068089502*z3*z6+50092880726716435214803260421146270553713249937192830605727461950215072333489213290817696683879909720345350129342*z4*z6+577014942825878237410919830996081423363976775867051621519143346919634600821873081382457730593973364753397607734600*z1*z9+93204486186994687610127869096827974868720823082919977275187046472314934972156818986014287999835299057729702971960*z3*z9-248800723548683742634187452228174849664062154974533234435587182500954583693565368032679893782668419829608355940280*z4*z9+5478247080403082583560566601404356838104508575653804140533246244657150211171443197106397863164209370032642503173030*z1*z10-29374856762320461082902556404161516346558441237453426876904027617890156965072595325010800405970985551430366449820820*z3*z10-19660204667847959380360596458822016776402536736367327520344828601885842641217048788867492933158478939886538366213830*z4*z10+35009467542236474301547290800028615011660275611918720631715532566960083839680228654090455546941079256149461024375*z1+4302705369007792234468278419402106497640334353141807378377034051124443136632939306886194176124895888500454116748*z3-94616889796863072089770620169371119870133913001814955138453696966158574038844106878104145092933224638119758543459*z4, 2832492784095457717889991030396706412997034658884633301648522852100119816705201268607674297035991764413269033324870000*z4*z6*z10^2+193491310299764535971155861953751736281702283092295295453155196960793870929094762095306951481440712387916264613767625*z4*z5*z10-77489701520303156305950937832134574929970954775484366414817397008814076839876885207045628821616938323373804253250400*z1*z6*z10-99282569855061169552502459251012304712143604087184405688518690607756329989374082998189976254391405236952527013825600*z3*z6*z10+226706310304469067058573834545190982414923941992825896499805898203623876218252740827252069466778129348498504373082150*z4*z6*z10+1348796211984804438949224623619601697532350001502236326253829841233688310797065011013130018541205636935739654213440000*z1*z9*z10-3310858569154294849685100768724620193941868513280594783053599464413841345276327349144897404630213316674498097232233600*z3*z9*z10+1983451597160824322872979619637671494111857773890096750107793878680049879396662459836671770380540256890528247649680000*z4*z9*z10-52919945959086248289756146454024689236306967626829839695826366448012173492447625234604464042792400427122271972712578125*z1*z10^2+86943729398974931236305843756333847178605126598254441502913659573410939892139138134533512846126617652041393553500156250*z3*z10^2-347675723745134947209716685484090981574225636276790229008582916085064129246425285756912012904356206597670465782331713125*z4*z10^2-470815950205726134376349736891663144721329698860893968653576829000153770047483357523347706323685751700584559486600*z1*z2+1411721086191218857456135734723039855482599060702048255110502399850531828214961904001331873549635769800146769343772*z2*z3-775392837479825820340649471557935480446040681469323123663691401331839819283195195712185311976694704658846177321236*z2*z4+331321568933769319814835703953889404578245708931951371161977551931683719796595980209697100911905551790625347846068*z1*z5+231104987839482256990838787104685370134687695013883361166874828596937976347083910374337282052342205882082526381318*z3*z5+284651398810700683035029750459123106469497996954319114236061228319889947329899006728144358495127081531115537837775*z4*z5+8147148318328389166428479457132731540199066075582520035874292881218079940859288752313505181355118951582997438918*z1*z6-1150811425351755996383831491860004003888660470476784745632129528370458934145257727992426108233350376008122173748118*z3*z6+1258448497213890981258819082285664397163305908634352197211355156234719257063772358011342135808283740630979758285318*z4*z6+6300518781434656775142097781046957154797002568740175638784116455331965084338788441423202680693674839988972563571200*z1*z9-15178999487261454671557904271668710075647661574497131049049409207090230017643133761571188624800102796523610434153600*z3*z9+8973938572748671872988194080271951736043017511103034447220453971622012553994092909881257132847144193353613379113600*z4*z9-76140950306059304361924344842122720729295129153771339023878193092190826481877009179980983379528231527996805467214650*z1*z10-267679722998231194444136810350853031878623071627049893893349883736563785026917201175027405823769936459123767058484700*z3*z10-1891352269143817996273389827251413504496201475043384566050300701708298020283011790811691296713903631151844495734879750*z4*z10+1031938354027916175703310379814014308462322176407753376720724066615879809284185469849764972519334655460428978710275*z1-625544000849857958827690045640582147538743523417268983757527933759266264377534447139903730093291233888020803870778*z3-4241570302158674820214008883874661150374242235556221804463631801869154211076436531569910860705274103635282052322061*z4, 524535700758418095905553894517908594999450862756413574379356083722244410500963197890310055006665141558012783949050*z3*z6*z10^2+14906729965506756680883975739658989953796117633870270390473013112186678626403242170973389496616880855758607644100*z4*z5*z10-2018895866457209271987403511437259999940899452776565050565991752622075592315395377491666172911041865964453897200*z1*z6*z10+2056297724766927066147752797783231250076498545139804716141735555606592824175958725095758646637922460540072006850*z3*z6*z10+11830048462419614187538828836477247796335095560206625315088656550915180260113113714251907671119169636449484821800*z4*z6*z10+33088276153853276077679958320023460395313907762097161529484056846677614765882134047222498648010071783259405440000*z1*z9*z10-183231867355060063670198749754634611347919294164945413123248391840912099721156470185822650980013939296442509302400*z3*z9*z10+151602834776180905030150033544526755881570100903340054919047574059073623482512261158339819029504731498236332400000*z4*z9*z10+4011795460482730870797867534823279516378759784279583258715931222380510978526069940630721711262537944075823325406875*z1*z10^2-14833275724766671200648532218144277751364563239189053021619038788480401853919102828672757171379434192466158626756825*z3*z10^2-10359810369300333213974797877738261042788091344069631384902881151990825414851748029826949055734810650073315493030000*z4*z10^2-40799296974282677296309714847607279891197450909648724405488760267573294316356927591319198900313732158930052400*z1*z2+133204431018492304106400080528644241523276832107027231859822713150971827305859314912727448091337064048251196912*z2*z3-83119096696748248640683881500009962325277200874859211599454588303425264092048175480931645282647847808006905056*z2*z4+28218598219195866058663976141809748100428185655431282402239773393452796065574283529519011912513201995923760228*z1*z5+22152198799960093857969372594763462022338597654007941131741376603743191962442610567248209416066397718437297628*z3*z5+15209159599279159517889892116491339618034913791154976889616066920874687363945528183345433092851099604162738500*z4*z5+31696336493326280368923790606739664837568371495264566892670880370778518622269225658751641150791166620713439128*z1*z6-53749249388823881748790220962222347401256026599842076921261201678644331246503995355202621866528418972619415128*z3*z6+61548055540497396488137113568231970178345100314131553186420943328999892024036628552847275790096149881244786328*z4*z6+166946557263742836483246670774696074425132506529746252876376533489354660098349453361176135715934936639146880000*z1*z9-845149532228539473866477028277628689621718952011856392456040848058961390719749502243532316395995851329181884800*z3*z9+684715366154384986009086512111879477350026934440754046780231580923175708428263806441832414506075236148226358400*z4*z9+45804004818624496805452322861401879753393026239833628430887220317899084212360947693524486068367356453207735765750*z1*z10-198528773018408504194628401304249444151464912852324918953467987573093298329536331750255335087819035838031881088450*z3*z10-2274553454568973229009090111034286981280235706493535555722869605467859730315615519399878004832869984894535950800*z4*z10+122634475221529229542764549558797441706461817422769932112247195257559450537665944420482322513712303618129996075*z1-411289933052176733259701560671821452942729150381751736755181263345216254993656697885827568551274468605772944913*z3+12033504279303142614973801543643178662775163695822386762760861238127255820572079282683148935507504782446499544*z4, 236041065341288143157499252533058867749752888240386108470710237675009984725433439050639524752999313701105752777072500*z1*z6*z10^2+11433513420361839367915118531222294830319376283690413162934427220072349919350689174747101563646322414728089130022675*z4*z5*z10-5087626662655560725218601152847825504687713895315512821486447645313721652838109893429645048417308269922666085032600*z1*z6*z10-9348693556761163408557281758880557798186814179151614008006670839530697140853001055392940024612944834558605606175950*z3*z6*z10+13666078827386913223951903191784954895497835126473325710623380529669953206553021172045923628558520112724093517898250*z4*z6*z10+124813447860373175423647721183366020673737528637178641687180043527915561743936417194159042286571450275024394968200000*z1*z9*z10-234801113207911432323566716826449347271806929093816543408770208483611362103677046039597039731184107095754871295013000*z3*z9*z10+111345438017081424493999505078085330517040157872756527440628840092398498426432105315422209764715571139355359822085000*z4*z9*z10-11694136751539387766553437490679118926894913917058802753832277551554925532765429964197025543839420755075367143638540000*z1*z10^2+22418043627168368483738306062464461486923212175751113664136738297902492507395681583609919640398063856190563261007859375*z3*z10^2-31793142406235013334490767058884961380498499145968817420685663989046308894783504076708526987699735669499274685944730625*z4*z10^2-24167735435712121624861126924638847565054436559784147298718919103769849185567022758480055348797055258850625711000*z1*z2+61520597845014839261720900946524841201665459156152489925709565960902900156225940986332925874680780130811385423892*z2*z3-25130071575138722171087440829775934493363770760973429741024838672989772714204156203886284690121532459268119795996*z2*z4+17590269550601381755535002274366150555145848946738221318294142195147450015406982616519452817063829263979967846548*z1*z5+10580943126523127655671545613571013864921486645786798478102161977251626282284863200675722868549324628798990523898*z3*z5+21685510505272147124369687362251961409935702154553766816253160302234051837937926800750397897456060391966648758325*z4*z5-17853065380597074553944413982150822751306641481476200121515891972563388586656428453361425182647133018438408515102*z1*z6-84331187943704735438881120129870276367931153711299106256881615714172858684330851198253648779822132013938355564498*z3*z6+90403069607750553385526545923453422312133137320011714535733244650780179656514272507196284672685908146916168544498*z4*z6+574805918297028582938177103354943847273503608504411069068343360235468536247887125694474332839419757387407533236800*z1*z9-1073613891324859326549320248687856306778890364410606052332952264660458283071008012268585514063887983942507508944200*z3*z9+504867630069457291414122105335165701239476380331171183853412234065570892348123615560928490290227765494861212317000*z4*z9-67403963881875413136689305975065063519326347670889913119267115372516040502884389533819523617441593502750925485737100*z1*z10+130481445167096315533178764520502146561399856568052873554669754865234313554522908786700195848648588641375212440950800*z3*z10-210560929752626541743983094595992962786161504607063956885692545243233994246820839923358871210946650828181110743253100*z4*z10-26734777490836416228804500717400517152115307516348335198622734627573481128085562683060791524588045522683028425100*z1+268476369900412180491006603771360961599551816332130741259238411623565744471710880886572448047580705106607569919117*z3-487566116630139387182960850334660860892885690417650870555035618403558415180957086388498310582377799162850469101671*z4, 1416246392047728858944995515198353206498517329442316650824261426050059908352600634303837148517995882206634516662435000*z4*z5*z10^2-35325825560025826690458139146727666594967385859350819130393235703801743062288056758505897473739756646181942758498425*z4*z5*z10+28688712800384041702553776890615061425838560212775033900379620822400712369620542158010650891511059099344583686390800*z1*z6*z10+29162624249494758896665293435136722676440171704306867075856099245783740833636472779668083086468614577971428468266000*z3*z6*z10-51870657049013738168893311555382463935964858358946073336834969105788499768248080003062270750542492669024273897300950*z4*z6*z10-519638314581020946819040822712696366535654489775283143910053253748274762035591499350093015384806020170410852408160000*z1*z9*z10+1374795448093004217502616657564614172747175305105712808957144167661618054367599352610671478694411551478132388585464800*z3*z9*z10-864068426859707686713337817713349031847423712964754731975921684267029287373730552990123768653210325980680106700300000*z4*z9*z10+14929774783509300917809253365919639041000421010281183268141379447660039008732931568643084768117381495402864606665390625*z1*z10^2-33001155814034691307007311904899207849901053539763208984739103994295983353829856187407347198617465423731626195059218750*z3*z10^2+140254894405012888016862110777102547580995951849223227120252073923123378714521223319269967304876575236020401232656978125*z4*z10^2+155455081811181413066154822828373314689650538881552914391454956774397557740551776513595698036980442486781880241800*z1*z2-272392502520480653498023052777032853832199901945522853307343579569418640680958668845096536633471668745394600435708*z2*z3+55037243073661296887169281784838174288786864621014958573584570885830571408541269668897345172709448955979993781204*z2*z4-66080337193181982483588212527314187151522720758035512394731917839458316847181905100603011780788751063037625472852*z1*z5-28497937792751142111885868859442308567922850668727112022892656651129083435497648420486123739218867764104030446102*z3*z5-85461683387378861471351956071963095658259241335026186262332382560391014335927680123917393608308276459951701626775*z4*z5+53612905878891928083453328430253780100101667677135516416668399491362599842882239593118028687615126574452525569498*z1*z6+314222117668624180159770576027233672492629351214578061512143978994950413773266724887654582170241861272890479730102*z3*z6-322913681121036755164858773079804774222688025485010192602631488580115048719808143184966635041049786362138718937702*z4*z6-2436160318399689743227726318357648988786152101378337662206201810138608922823032954119814003395791130420451740742400*z1*z9+6302727693911711472629736388342427301194318379798685282844665972847668616448994999546012901978650276475294410668000*z3*z9-3906337218240550731779793813008289648241057541792325877157152546246382795973032679811956630886947258682551780568800*z4*z9-14523136676100634494767351284940310469606681926222591934640105447447453139191690064595996866551221587781327628491950*z1*z10+146775576352849427609178570983813707398843366821517138568036820500884295113116628789074821843077987950328150975621300*z3*z10+781892199802629555056136820851976336101692148297061576407472578370157928431894861904704041588395355333300607523721350*z4*z10-469002166854124311435245729170678967643067372796103850842511527744687418620992060191716033780623829141973623966975*z1+737614171099936388688007253287260403652660343905341535909766946641539223011048113376662777719141770789473486280342*z3+1420073074377355453406403764717514515620058405778768611345644586159898391465499026157961166666718978824852549636229*z4 msolve-0.6.5/input_files/bug_68.ms000066400000000000000000000000471456710632100170110ustar00rootroot00000000000000x,y,z 257 0, x*x+y*y+z*z, x+y+z, x+y*z msolve-0.6.5/input_files/cp_d_3_n_4_p_2.ms000066400000000000000000000064661456710632100203610ustar00rootroot00000000000000x1, x2, x3, x4 0 -7*x1^3+22*x1^2*x2-56*x1*x2^2+80*x2^3-55*x1^2*x3-44*x2^2*x3-73*x1*x3^2-75*x2*x3^2+23*x3^3-94*x1^2*x4-62*x1*x2*x4+71*x2^2*x4-4*x1*x3*x4-10*x2*x3*x4+75*x3^2*x4-10*x1*x4^2-40*x2*x4^2+6*x3*x4^2+37*x4^3+87*x1^2+97*x1*x2-17*x2^2-83*x1*x3-7*x2*x3-92*x3^2+62*x1*x4+42*x2*x4+74*x3*x4-23*x4^2-82*x1-50*x2+72*x3+87*x4+44, 29*x1^3+98*x1^2*x2-8*x1*x2^2-10*x2^3-23*x1^2*x3-29*x1*x2*x3+31*x2^2*x3-49*x1*x3^2+95*x2*x3^2+30*x3^3+10*x1^2*x4+95*x1*x2*x4-51*x2^2*x4-47*x1*x3*x4+x2*x3*x4-27*x3^2*x4-81*x1*x4^2+55*x2*x4^2-59*x3*x4^2-87*x4^3-61*x1^2+11*x1*x2+77*x2^2+40*x1*x3+x2*x3-15*x3^2+91*x1*x4-28*x2*x4-96*x3*x4+47*x4^2+68*x1+16*x2+72*x3-90*x4+43, 4884*x1^4+1058*x1^3*x2+1072*x1^2*x2^2-11136*x1*x2^3+6120*x2^4+10557*x1^3*x3+32954*x1^2*x2*x3-50304*x1*x2^2*x3+41100*x2^3*x3-2066*x1^2*x3^2+6525*x1*x2*x3^2+18105*x2^2*x3^2+23221*x1*x3^3-12198*x2*x3^3-13305*x3^4+6009*x1^3*x4-876*x1^2*x2*x4-13532*x1*x2^2*x4-146*x2^3*x4+4227*x1^2*x3*x4-13506*x1*x2*x3*x4+3486*x2^2*x3*x4-2754*x1*x3^2*x4+14395*x2*x3^2*x4-11169*x3^3*x4+5353*x1^2*x4^2+1670*x1*x2*x4^2-13678*x2^2*x4^2+1696*x1*x3*x4^2+13102*x2*x3*x4^2-3150*x3^2*x4^2+5188*x1*x4^3-7256*x2*x4^3-5506*x3*x4^3+2030*x4^4+7388*x1^3+1339*x1^2*x2+11363*x1*x2^2+5752*x2^3+7281*x1^2*x3+47938*x1*x2*x3+4093*x2^2*x3+8352*x1*x3^2-228*x2*x3^2+19031*x3^3-10980*x1^2*x4+10956*x1*x2*x4-19816*x2^2*x4+6410*x1*x3*x4-36652*x2*x3*x4+6594*x3^2*x4-5988*x1*x4^2-4895*x2*x4^2+14545*x3*x4^2-2540*x4^3+1351*x1^2+6134*x1*x2+19638*x2^2+8241*x1*x3+11456*x2*x3-17450*x3^2-19660*x1*x4+9392*x2*x4-6306*x3*x4-5946*x4^2+5520*x1-13474*x2+3868*x3+8656*x4-4752, 9432*x1^4+5542*x1^3*x2-20132*x1^2*x2^2+27788*x1*x2^3-10110*x2^4-3368*x1^3*x3+9352*x1^2*x2*x3-14129*x1*x2^2*x3+26*x2^3*x3+120*x1^2*x3^2+7083*x1*x2*x3^2-6618*x2^2*x3^2+6080*x1*x3^3-1399*x2*x3^3-5100*x3^4+6706*x1^3*x4+19916*x1^2*x2*x4-49497*x1*x2^2*x4+24000*x2^3*x4-1064*x1^2*x3*x4+19502*x1*x2*x3*x4-33119*x2^2*x3*x4+9421*x1*x3^2*x4+12806*x2*x3^2*x4+7905*x3^3*x4+94*x1^2*x4^2+6354*x1*x2*x4^2-53715*x2^2*x4^2+13135*x1*x3*x4^2+44*x2*x3*x4^2+7153*x3^2*x4^2+13217*x1*x4^3-25740*x2*x4^3+6559*x3*x4^3+4335*x4^4-2070*x1^3+10101*x1^2*x2+28098*x1*x2^2-14660*x2^3-12057*x1^2*x3+3120*x1*x2*x3-19168*x2^2*x3-13680*x1*x3^2-8659*x2*x3^2+284*x3^3-22662*x1^2*x4+28120*x1*x2*x4+29914*x2^2*x4-15894*x1*x3*x4-10030*x2*x3*x4-14*x3^2*x4-42410*x1*x4^2+1626*x2*x4^2-4028*x3*x4^2-9084*x4^3-1357*x1^2-8106*x1*x2-23092*x2^2-5888*x1*x3-5342*x2*x3-767*x3^2+20917*x1*x4-4238*x2*x4+3949*x3*x4+12749*x4^2-15229*x1-9610*x2+4159*x3-5308*x4+3108, -2712*x1^4-9377*x1^3*x2+5114*x1^2*x2^2-199*x1*x2^3+43*x2^4-8179*x1^3*x3-3987*x1^2*x2*x3+13836*x1*x2^2*x3-5574*x2^3*x3+18830*x1^2*x3^2+20994*x1*x2*x3^2-9296*x2^2*x3^2+8409*x1*x3^3-9231*x2*x3^3-8613*x3^4+3992*x1^3*x4-11770*x1^2*x2*x4+8081*x1*x2^2*x4-1921*x2^3*x4+24882*x1^2*x3*x4+15450*x1*x2*x3*x4-296*x2^2*x3*x4+5393*x1*x3^2*x4+30015*x2*x3^2*x4-9222*x3^3*x4+11130*x1^2*x4^2-2429*x1*x2*x4^2+10906*x2^2*x4^2+24122*x1*x3*x4^2+30824*x2*x3*x4^2-40788*x3^2*x4^2+4109*x1*x4^3-1561*x2*x4^3-33156*x3*x4^3+4983*x4^4-649*x1^3-1077*x1^2*x2-3918*x1*x2^2+216*x2^3-827*x1^2*x3-33770*x1*x2*x3+9667*x2^2*x3+29736*x1*x3^2-5742*x2*x3^2-6066*x3^3+2284*x1^2*x4-3918*x1*x2*x4-120*x2^2*x4+37288*x1*x3*x4-29118*x2*x3*x4+27496*x3^2*x4+4981*x1*x4^2+3592*x2*x4^2+59180*x3*x4^2-10808*x4^3+4406*x1^2+13772*x1*x2-7367*x2^2+8694*x1*x3+4772*x2*x3-1500*x3^2+949*x1*x4+15841*x2*x4-36838*x3*x4-19651*x4^2+6078*x1-4497*x2+6930*x3+11772*x4-12744 msolve-0.6.5/input_files/eco11-31.ms000066400000000000000000000011641456710632100170510ustar00rootroot00000000000000x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10 1073741827 x0*x1*x10+x1*x2*x10+x2*x3*x10+x3*x4*x10+x4*x5*x10+x5*x6*x10+x6*x7*x10+x7*x8*x10+x8*x9*x10+x0*x10-1, x0*x2*x10+x1*x3*x10+x2*x4*x10+x3*x5*x10+x4*x6*x10+x5*x7*x10+x6*x8*x10+x7*x9*x10+x1*x10-2, x0*x3*x10+x1*x4*x10+x2*x5*x10+x3*x6*x10+x4*x7*x10+x5*x8*x10+x6*x9*x10+x2*x10-3, x0*x4*x10+x1*x5*x10+x2*x6*x10+x3*x7*x10+x4*x8*x10+x5*x9*x10+x3*x10-4, x0*x5*x10+x1*x6*x10+x2*x7*x10+x3*x8*x10+x4*x9*x10+x4*x10-5, x0*x6*x10+x1*x7*x10+x2*x8*x10+x3*x9*x10+x5*x10-6, x0*x7*x10+x1*x8*x10+x2*x9*x10+x6*x10-7, x0*x8*x10+x1*x9*x10+x7*x10-8, x0*x9*x10+x8*x10-9, x9*x10-10, x0+x1+x2+x3+x4+x5+x6+x7+x8+x9+1 msolve-0.6.5/input_files/elim-31.ms000066400000000000000000000000661456710632100170670ustar00rootroot00000000000000t, w, x, y, z 1073741827 w^4, x^4, w*y^3-x*z^3, t*z-1 msolve-0.6.5/input_files/elim-qq.ms000066400000000000000000000000551456710632100172630ustar00rootroot00000000000000t, w, x, y, z 0 w^4, x^4, w*y^3-x*z^3, t*z-1 msolve-0.6.5/input_files/input-overflow-16.ms000066400000000000000000000000451456710632100211410ustar00rootroot00000000000000y,x 65519 x^2+128333*x*y-12*y, y^2-x msolve-0.6.5/input_files/kat6-31.ms000066400000000000000000000004011456710632100167770ustar00rootroot00000000000000x1,x2,x3,x4,x5,x6 1073741827 x1+2*x2+2*x3+2*x4+2*x5+2*x6-1, x1^2+2*x2^2+2*x3^2+2*x4^2+2*x5^2+2*x6^2-x1, 2*x1*x2+2*x2*x3+2*x3*x4+2*x4*x5+2*x5*x6-x2, x2^2+2*x1*x3+2*x2*x4+2*x3*x5+2*x4*x6-x3, 2*x2*x3+2*x1*x4+2*x2*x5+2*x3*x6-x4, x3^2+2*x2*x4+2*x1*x5+2*x2*x6-x5 msolve-0.6.5/input_files/kat7-qq.ms000066400000000000000000000005131456710632100172020ustar00rootroot00000000000000x1,x2,x3,x4,x5,x6,x7 0 x1+2*x2+2*x3+2*x4+2*x5+2*x6+2*x7-1, x1^2+2*x2^2+2*x3^2+2*x4^2+2*x5^2+2*x6^2+2*x7^2-x1, 2*x1*x2+2*x2*x3+2*x3*x4+2*x4*x5+2*x5*x6+2*x6*x7-x2, x2^2+2*x1*x3+2*x2*x4+2*x3*x5+2*x4*x6+2*x5*x7-x3, 2*x2*x3+2*x1*x4+2*x2*x5+2*x3*x6+2*x4*x7-x4, x3^2+2*x2*x4+2*x1*x5+2*x2*x6+2*x3*x7-x5, 2*x3*x4+2*x2*x5+2*x1*x6+2*x2*x7-x6 msolve-0.6.5/input_files/kat8-qq-truncate.ms000066400000000000000000000006531456710632100210330ustar00rootroot00000000000000x1,x2,x3,x4,x5,x6,x7,x8 0 x1+2*x2+2*x3+2*x4+2*x5+2*x6+2*x7+2*x8-1, x1^2+2*x2^2+2*x3^2+2*x4^2+2*x5^2+2*x6^2+2*x7^2+2*x8^2-x1, 2*x1*x2+2*x2*x3+2*x3*x4+2*x4*x5+2*x5*x6+2*x6*x7+2*x7*x8-x2, x2^2+2*x1*x3+2*x2*x4+2*x3*x5+2*x4*x6+2*x5*x7+2*x6*x8-x3, 2*x2*x3+2*x1*x4+2*x2*x5+2*x3*x6+2*x4*x7+2*x5*x8-x4, x3^2+2*x2*x4+2*x1*x5+2*x2*x6+2*x3*x7+2*x4*x8-x5, 2*x3*x4+2*x2*x5+2*x1*x6+2*x2*x7+2*x3*x8-x6, x4^2+2*x3*x5+2*x2*x6+2*x1*x7+2*x2*x8-x7 msolve-0.6.5/input_files/mq_2_1.ms000066400000000000000000000000511456710632100167700ustar00rootroot00000000000000x 251 -68*x^2+34*x-107, 104*x^2+122*x+72 msolve-0.6.5/input_files/multy-16.ms000066400000000000000000000000271456710632100173130ustar00rootroot00000000000000x,y 65521 x-y^2, y^3-y msolve-0.6.5/input_files/multy-31.ms000066400000000000000000000000341456710632100173060ustar00rootroot00000000000000x,y 1073741827 x-y^2, y^3-y msolve-0.6.5/input_files/multy-qq.ms000066400000000000000000000000231456710632100175020ustar00rootroot00000000000000x,y 0 x-y^2, y^3-y msolve-0.6.5/input_files/nf-16.ms000066400000000000000000000002641456710632100165470ustar00rootroot00000000000000x1,x2,x3,x4,x5 65521 x1+2*x2+2*x3+2*x4+2*x5-1, x1^2+2*x2^2+2*x3^2+2*x4^2+2*x5^2-x1, 2*x1*x2+2*x2*x3+2*x3*x4+2*x4*x5-x2, x2^2+2*x1*x3+2*x2*x4+2*x3*x5-x3, 2*x2*x3+2*x1*x4+2*x2*x5-x4 msolve-0.6.5/input_files/nf-31.ms000066400000000000000000000002711456710632100165420ustar00rootroot00000000000000x1,x2,x3,x4,x5 1073741827 x1+2*x2+2*x3+2*x4+2*x5-1, x1^2+2*x2^2+2*x3^2+2*x4^2+2*x5^2-x1, 2*x1*x2+2*x2*x3+2*x3*x4+2*x4*x5-x2, x2^2+2*x1*x3+2*x2*x4+2*x3*x5-x3, 2*x2*x3+2*x1*x4+2*x2*x5-x4 msolve-0.6.5/input_files/nf-8.ms000066400000000000000000000002621456710632100164660ustar00rootroot00000000000000x1,x2,x3,x4,x5 101 x1+2*x2+2*x3+2*x4+2*x5-1, x1^2+2*x2^2+2*x3^2+2*x4^2+2*x5^2-x1, 2*x1*x2+2*x2*x3+2*x3*x4+2*x4*x5-x2, x2^2+2*x1*x3+2*x2*x4+2*x3*x5-x3, 2*x2*x3+2*x1*x4+2*x2*x5-x4 msolve-0.6.5/input_files/nf-lm-bug.ms000066400000000000000000000001121456710632100174740ustar00rootroot00000000000000a,b,c 101 -1+c+b, -1+b+c*a+2*a*b, -1+c+b+a^3, -1+b+c*a+2*a^3, 5+c*b+c^2*a msolve-0.6.5/input_files/nonradical_radicalshape-31.ms000066400000000000000000000001751456710632100227540ustar00rootroot00000000000000x, y 1073741827 20958084*x^2+7224084*x*y+622521*y^2, 6651834*x^2+5619123*x*y+770853*y^2, 2111209*x^2+2839162*x*y+954529*y^2 msolve-0.6.5/input_files/nonradical_radicalshape-no-square-31.ms000066400000000000000000000003711456710632100246620ustar00rootroot00000000000000x,y,z 1073741827 5184*x^2+5328*x*y-3312*x*z+1369*y^2-1702*y*z+529*z^2+12528*x+6438*y-4002*z+7569, 1936*x^2+2552*x*y+8624*x*z+841*y^2+5684*y*z+9604*z^2-2024*x-1334*y-4508*z+529, 100*x^2-1220*x*y-160*x*z+3721*y^2+976*y*z+64*z^2-580*x+3538*y+464*z+841 msolve-0.6.5/input_files/nonradical_radicalshape-no-square-qq.ms000066400000000000000000000003601456710632100250560ustar00rootroot00000000000000x,y,z 0 5184*x^2+5328*x*y-3312*x*z+1369*y^2-1702*y*z+529*z^2+12528*x+6438*y-4002*z+7569, 1936*x^2+2552*x*y+8624*x*z+841*y^2+5684*y*z+9604*z^2-2024*x-1334*y-4508*z+529, 100*x^2-1220*x*y-160*x*z+3721*y^2+976*y*z+64*z^2-580*x+3538*y+464*z+841 msolve-0.6.5/input_files/nonradical_radicalshape-qq.ms000066400000000000000000000001161456710632100231450ustar00rootroot00000000000000x, y 0 y^4-2*y^2+1, x*y^2+3*y^3-2*x*y-6*y^2+x+3*y, 9*y^3+x^2-6*x*y-9*y^2+9*y msolve-0.6.5/input_files/nonradical_shape-31.ms000066400000000000000000000012601456710632100214300ustar00rootroot00000000000000x1, x2, x3, x4 1073741831 570511439*x4^11+353378708*x4^10+599390609*x4^9+1049120212*x4^8+826752179*x4^7+19533939*x4^6+45047444*x4^5+448227342*x4^4+74356583*x4^3+17844919*x4^2+627145600*x4+372416000, 735241234*x4^10+884961191*x4^9+136721026*x4^8+198304612*x4^7+640439652*x4^6+417177801*x4^5+836782561*x4^4+537655879*x4^3+147944788*x4^2+x1+702680360*x4+540721923, 904966252*x4^10+698412071*x4^9+618307600*x4^8+511091141*x4^7+316773880*x4^6+366222184*x4^5+961264978*x4^4+76338300*x4^3+25585315*x4^2+x2+855028007*x4+347706282, 290319951*x4^10+366206486*x4^9+405889704*x4^8+213561267*x4^7+999862911*x4^6+838518850*x4^5+772320120*x4^4+264387201*x4^3+893645500*x4^2+2*x3+291291731*x4+117559519 msolve-0.6.5/input_files/nonradical_shape-qq.ms000066400000000000000000000013211456710632100216240ustar00rootroot00000000000000x1, x2, x3, x4 0 x4^18+48/5*x4^17+984/25*x4^16+12082/125*x4^15+99576/625*x4^14+104832/625*x4^13+55671/625*x4^12-6336/125*x4^11-88416/625*x4^10-83284/625*x4^9-22848/625*x4^8+23136/625*x4^7+7091/125*x4^6+13104/625*x4^5-1944/625*x4^4-7398/625*x4^3-1944/625*x4^2+729/625, 97*x4^17-73*x4^16-4*x4^15-83*x4^14-10*x4^13+62*x4^12-82*x4^11+80*x4^10-44*x4^9+71*x4^8-17*x4^7-75*x4^6-10*x4^5-7*x4^4-40*x4^3+42*x4^2+1451*x3-50*x4+23, 75*x4^17-92*x4^16+6*x4^15+74*x4^14+72*x4^13+37*x4^12-23*x4^11+87*x4^10+44*x4^9+29*x4^8+98*x4^7-23*x4^6+10*x4^5-61*x4^4-8*x4^3-29*x4^2+95*x4+4784*x2+11, -49*x4^17-47*x4^16+40*x4^15-81*x4^14+91*x4^13+68*x4^12-10*x4^11+31*x4^10-51*x4^9+77*x4^8+95*x4^7+x4^6+x4^5+55*x4^4-28*x4^3+16*x4^2+30*x4+4784*x1-27 msolve-0.6.5/input_files/one-16.ms000066400000000000000000000002321456710632100167200ustar00rootroot00000000000000x,y,z 65521 -62*x^2+97*y^2-73*y*z-56*y+87, -44*x*y+71*x*z-17*y*z+62*x-82*y+80*z, 37*x^2-23*x*y+87*x*z+74*y+72*z+6, -47*x^2+40*y^2-81*y*z+91*z^2+11*x-49*z msolve-0.6.5/input_files/one-31.ms000066400000000000000000000002371456710632100167220ustar00rootroot00000000000000x,y,z 1073741827 -62*x^2+97*y^2-73*y*z-56*y+87, -44*x*y+71*x*z-17*y*z+62*x-82*y+80*z, 37*x^2-23*x*y+87*x*z+74*y+72*z+6, -47*x^2+40*y^2-81*y*z+91*z^2+11*x-49*z msolve-0.6.5/input_files/one-qq.ms000066400000000000000000000002261456710632100171160ustar00rootroot00000000000000x,y,z 0 -62*x^2+97*y^2-73*y*z-56*y+87, -44*x*y+71*x*z-17*y*z+62*x-82*y+80*z, 37*x^2-23*x*y+87*x*z+74*y+72*z+6, -47*x^2+40*y^2-81*y*z+91*z^2+11*x-49*z msolve-0.6.5/input_files/radical_shape-31.ms000066400000000000000000000002541456710632100207170ustar00rootroot00000000000000x, y, z 1073741827 1073741825*z^3+1073741824*z^2+x+1073741822*z+1073741820, 1073741826*z^3+z^2+y+1073741826*z+1, z^4+1073741826*z^3+1073741826*z^2+1073741826*z+1073741826 msolve-0.6.5/input_files/radical_shape-qq.ms000066400000000000000000000001021456710632100211050ustar00rootroot00000000000000x, y, z 0 -2*z^3-3*z^2+x-5*z-7, -z^3+z^2+y-z+1, z^4-z^3-z^2-*z-1 msolve-0.6.5/input_files/realroot-extract.ms000066400000000000000000000063011456710632100212150ustar00rootroot00000000000000x2, x3, x4 0 44*x2+89*x3+68*x4-399618188733716626755, 3541593292951995450990310372960*x3*x4^2+1945129239286751919414305247933037053312*x4^3+3934465960412942563221192837274463643877*x3^2-6160384484930804102826761583954813432864*x3*x4-14762938525851362040635945282536216653225156172528*x4^2-17666114162036664830285741944402853632429598662969829575790*x3+32424589106336347293933964960245539105941703052309739807584*x4-20927023795060259240401449899122357771276530794982866322399620183619, 885398323237998862747577593240*x3^2*x4-371541540088480703708350440616422807936*x4^3+1124617427400488171147647847820165445509*x3^2-3975519936251969185573941899244038227535359168728*x3*x4+854461547485243485091044709341730710308917715344*x4^2-5049635722096270294004840036858123777397405290362075411390*x3+4558815958060872500465546554808567124687618955848218381488*x4-5981725576062516117963907776340935076861123347164376399984701081203, 1216575129605833071064193540279629438242146963993362985294582671957885980422454881835547115520*x4^4-4480500074571222313461555550712328368478449324345890778229459806572786794031983323350*x3^3-5372173954435183355088559628849345823155944031307709946071853400935489844311854146212545484772651069824*x4^3+22713740521808162164164180829866365958885583624671058550325299785238915119989762815716533374386433218081*x3^2-9489540297202917593677549708586512211517715743137735970905260369269382833871244373867826060613624806672*x3*x4-3563398928159630847623779222986927849787492959782077342771003089845964248341475319116250198783932511984444965104*x4^2-11655753253219351337720027224622864114870131373108685141705703481733099567481843693026714651122073866543186374503677319940*x3+21393103651766611559095232296713879192326027965132012305652410479982360923795463524953347611948214651100282124375207293232*x4-13807237060788378542558162238655020068560522341195360845715840601185210051406775057881320256432349651588185157915974174346980800267, 2355716318826789088133648105529234624559076850806531776682055778067694294626606068157110687538211998908287040*x3^4-21154766027597930471377985068881332385907613229037238142385845656049100703749601452133252571427174055073119676303738096046457270*x3^3+5693822871463639181738363427864105154276053853135459997012363302951175976834964701245703391123217290835514705731560224652357270570751616*x4^3+47493422882526153952229605915906163768870143110401084649433436484971000346929405906617908893060067216428804267324311359227071610195121667304273281*x3^2+29052374790540607257545484155858879075243694508505348720831034973286577963836991006969926120424764470459282759894196721851917150431515248*x3*x4-119113119110180707186956342406300503521825138293780371590482893174678212683385897632485036593318360621562939134936094969092408901424478069625584*x4^2+189259162591860961639132830552894016037545162132363887076626104804918344668448901817491345405101816996231360871573576737430233749712133464915400862905202780*x3-140847856610967984418935201431274546929773957976597013105952773638398095845813724050068279605696677829816073315808746734913188934775649098348920318887478608*x4+157548860512296762335337030624565599318584348749022914263956180460928503551381043646998661863636457765077563948485097142138116423690425291173851514232817535769030613 msolve-0.6.5/input_files/reals_dim0-swapvar.ms000066400000000000000000000000321456710632100214110ustar00rootroot00000000000000x, y, z 0 x-1, y^2-4, z-3 msolve-0.6.5/input_files/reals_dim0.ms000066400000000000000000000000661456710632100177370ustar00rootroot00000000000000x,y,z 0 x+2*y+2*z-1, x^2+2*y^2+2*z^2-x, 2*x*y+2*y*z-y msolve-0.6.5/input_files/xy-qq.ms000066400000000000000000000000131456710632100167670ustar00rootroot00000000000000x,y 0 x, y msolve-0.6.5/interfaces/000077500000000000000000000000001456710632100151575ustar00rootroot00000000000000msolve-0.6.5/interfaces/msolve-to-julia-file-interface.txt000066400000000000000000000007561456710632100236320ustar00rootroot00000000000000msolve and its functionality is available in Julia via the package AlgebraicSolving.jl. Running your Julia REPL apply the following steps: using Pkg Pkg.add("AlgebraicSolving") # for stable version or Pkg.dev("AlgebraicSolving") # for developer version Moreover, msolve functionality is available via the Computer Algebra System OSCAR in Julia. Running your Julia REPL apply the following steps: using Pkg Pkg.add("Oscar") # for stable version or Pkg.dev("Oscar") # for developer version msolve-0.6.5/interfaces/msolve-to-maple-file-interface-macos.mpl000066400000000000000000000261261456710632100246740ustar00rootroot00000000000000# /* This file is part of msolve. # * # * msolve 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. # * # * msolve 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 msolve. If not, see # * # * Authors: # * Christian Eder # * Jorge Garcia Fontan # * Huu Phuoc Le # * Mohab Safey El Din */ FormatOutputMSolve:=proc(ll, _Z) local dim, deg, degquot, params, nvars, elim, den, cfs, i, varstr, linearform: dim:=ll[1]: if dim > 0 then return -1, [], []; fi; nvars:=ll[2]: degquot:=ll[3]: varstr:=ll[4]: linearform:=ll[5]: deg:=ll[6][1]: if nops(ll[6]) > 0 then elim:=PolynomialTools[FromCoefficientList](ll[6][2],_Z); else #computation failed return -2, [], []; fi: if nops(ll[5]) > 0 then den:=PolynomialTools[FromCoefficientList](ll[7][2],_Z); fi: params:=[]: cfs:=[1]: if degquot > 0 then for i from 1 to nvars-1 do params:=[op(params), PolynomialTools[FromCoefficientList](ll[8][i][1][2],_Z)]: cfs:=[op(cfs), ll[8][i][2]]: od: fi: return varstr, linearform, elim, den, [diff(elim, _Z), op(params)], cfs; end: GetRootsFromMSolve:=proc(l) local _Z, e, d, p, c, v, lf, sols, vals, i, sols_and_vals, realroots, OldDigits, mysols; local exist_gcd_p_e_nontrivial, length_p, gcd_p_e; v, lf, e, d, p, c := FormatOutputMSolve(l, _Z); if degree(e) = 0 then #positive dimension (-1) or computation failed (-2) return e, []; else return 0, [v,lf,e,d,p,c]; fi: end proc: ToMSolve:=proc(F, char, vars, fname) local i, fd, F2, str; fd:=fopen(fname, WRITE): for i from 1 to nops(vars)-1 do fprintf(fd, "%a, ", vars[i]): end; fprintf(fd, "%a ", vars[nops(vars)]): fprintf(fd,"\n"); fprintf(fd,"%d\n", char); if char = 0 then F2:=map(f->sort(expand(numer(f)), order=tdeg(op(vars))), F): F2:=remove(member, F2, [0]): for i from 1 to nops(F2)-1 do fprintf(fd, "%a,\n", F2[i]): od: fprintf(fd, "%a\n", F2[nops(F2)]): else F2:=map(f->sort(expand(numer(f)), order=tdeg(op(vars))) mod char, F): F2:=remove(member, F2, [0]): for i from 1 to nops(F2)-1 do fprintf(fd, "%a,\n", F2[i]): od: fprintf(fd, "%a\n", F2[nops(F2)]): fi: fclose(fd): # str := cat("sed -i -e ':a' -e 'N' -e '$!ba' -e 's/\\\n//g' ", fname): str := cat("sed -i '' -e ':a' -e 'N' -e '$!ba' -e 's/\\\\\\n//g' ", fname): lprint(str); system(str): end proc: GetOptions:=proc(opts) local str, msolve_path, fname1, fname2, file_dir, verb, param, nthreads, output, gb; str:=subs(opts,"verb"); if type(str, integer) then verb:=str; else verb:=0: end if; str:=subs(opts,"leadmons"); if type(str, integer) and str > 0 then gb:=str; else gb:=2: end if; str:=subs(opts,"elim"); if type(str, integer) and str > 0 then elim:=str; else elim:=0: end if; str:=subs(opts,"output"); if type(str, integer) then output:=str; else output:=0: end if; str:=subs(opts,"nthreads"); if type(str, integer) then nthreads:=str; else nthreads:=1: end if; if member("mspath", map(lhs, opts)) then str:=subs(opts, "mspath"); if type(str, string) then msolve_path:=str; else printf("Error in format options"); end if; else msolve_path := "../msolve"; end if; if member("file_dir", map(lhs, opts)) then str:=subs(opts, "file_dir"); if type(str, string) then file_dir:=str; else printf("Error in format options"); end if; else file_dir := "/tmp/"; end if; if member("file_in", map(lhs, opts)) then str:=subs(opts, "file_in"); if type(str, string) then fname1:=cat(file_dir,str); else printf("Error in format options"); end if; else fname1 := cat(file_dir, RandomTools[Generate](string(8,alpha)), ".ms");; end if; if member("file_out", map(lhs, opts)) then str:=subs(opts, "file_out"); if type(str, string) then fname2:=cat(file_dir,str); else printf("Error in format options"); end if; else fname2 := cat(file_dir, RandomTools[Generate](string(8,alpha)), ".ms");; end if; param:=0; msolve_path, fname1, fname2, file_dir, verb, param, nthreads, output, gb, elim; end proc; #Input. #F: list of polynomials with rational coefficients #fc: field characteristic #vars: list of variables #Optional argument: # {"mspath"=, # "verb"=, # "file_dir"=, # "file_in"=, # "file_out"=, # "leadmons"= <1 to get leading monomials only> # "elim"=} #Output. #[] -> an error occured during the computation #else returns a Groebner basis of the ideal generated by F for the # grevlex ordering over monomials involving variables in vars # with vars[1] > ... > vars[n] # if "leadmons"=1 is part of the third optional argument, then only # the leading monomials are returned MSolveGroebner:=proc(F, fc, vars, opts:={}) local results, dim, fname1, fname2, verb, param, msolve_path, file_dir, field_char, lsols, nl, i, gb, output, nthreads, str, elim; if type(F, list(polynom(rational))) = false then printf("First argument is not a list of polynomials with rational coefficients\n"); end if; if type(fc, integer)=true then if fc < 0 then error "Field characteristic cannot be negative"; end if; if fc > 0 and isprime(fc)=false then error "Field characteristic should be a prime number"; end if; if fc > 2^31 then error "Field characteristic is too large to be supported"; end if; if fc > 0 then field_char := fc; end if; else printf("Second argument should be a prime integer < 2^31\n"); end if; if not(indets(F) subset indets(vars)) then printf("Given variables do not match the variables in the input polynomials\n"); end if; msolve_path:="../msolve"; file_dir:="/tmp/"; fname1:=cat(file_dir, RandomTools[Generate](string(8,alpha)), ".ms"); fname2:=cat(file_dir, RandomTools[Generate](string(8,alpha)), ".ms"); while evalb(fname1=fname2) do fname2:=cat(RandomTools[Generate](string(8,alpha)), ".ms"); od: verb:=0; param:=0: nthreads:=1; output:=0; gb:=2; if nops(opts) > 0 then msolve_path, fname1, fname2, file_dir, verb, param, nthreads, output, gb, elim := GetOptions(opts); fi; ToMSolve(F, field_char, vars, fname1); str := cat(msolve_path, " -v ", verb, " -g ", gb, " -e ", elim, " -P ", param, " -t ", nthreads, " -f ", fname1, " -o ", fname2): try system(str): read(fname2): catch: printf("There has been an issue in msolve computation\n"); return []; end: results:=%: system(cat("rm ", fname2)); system(cat("rm ", fname1)); return results; end proc: #Input. #F: list of polynomials with rational coefficients #vars: list of variables #Optional argument: # {"mspath"=, # "verb"=, # "file_dir"=, # "file_in"=, # "file_out"=, # "output"= <1 to get mid points of isolating boxes>} #Output. #[] -> an error occured during the computation #[1] -> input system has infinitely many complex solutions #[-1, []] -> input polynomial system has no real solution #[0, [sols]] -> input polynomial system has finitely many complex solutions # sols is the list of real solutions given with isolating boxes with the following format # [vars[1] = [a1, b1], ..., vars[n] = [an,bn]] #if "output"=1 is part of the third (optional) argument output format is # [ vars[1] = (a1+b1)/2, ..., vars[n] = (an+bn)/2 ] MSolveRealRoots:=proc(F, vars, opts:={}) local results, dim, fname1, fname2, verb, param, msolve_path, file_dir, lsols, nl, i, j, gb, output, nthreads, str, sols, prec; if type(F, list(polynom(rational))) = false then printf("First argument is not a list of polynomials with rational coefficients\n"); end if; if not(indets(F) subset indets(vars)) then printf("Given variables do not match the variables in the input polynomials\n"); end if; msolve_path:="../msolve"; file_dir:="/tmp/"; fname1:=cat(file_dir, RandomTools[Generate](string(8,alpha)), ".ms"); fname2:=cat(file_dir, RandomTools[Generate](string(8,alpha)), ".ms"); while evalb(fname1=fname2) do fname2:=cat(RandomTools[Generate](string(8,alpha)), ".ms"); od: verb:=0; param:=0: nthreads:=1; output:=0; gb:=0; if nops(opts) > 0 then msolve_path, fname1, fname2, file_dir, verb, param, nthreads, output, gb := GetOptions(opts); fi; ToMSolve(F, 0, vars, fname1); if Digits <= 10 then prec:=128: else prec:= iquo(Digits/10)*128: fi: str := cat(msolve_path, " -v ", verb, " -P ", param, " -p ", prec, " -t ", nthreads, " -f ", fname1, " -o ", fname2): gb:=0; #Needed to avoid the user stops GB comp once a prime computation is done param:=0; try system(str): read(fname2): catch: printf("There has been an issue in msolve computation\n"); return []; end: results:=%: system(cat("rm ", fname2)); system(cat("rm ", fname1)); if nops(results) = 0 then printf("There has been an issue in msolve computation\n"); return []; end if; dim := results[1]; if dim = -1 then if verb >= 1 then printf("Algebraic set is empty\n"); end if; return [-1, []]; end if; if dim > 0 then if verb >= 1 then printf("Algebraic set has positive dimension\n"); end if; return [1]; end if; if dim = 0 then lsols := results[2]; nl := lsols[1]: sols:=[]: for i from 1 to nl do sols:=[op(sols), op(map(_p->[seq(vars[j] = _p[j], j=1..nops(vars))], lsols[i+1]))]; od: if output=1 then sols := map(_p->map(_c->lhs(_c)=(rhs(_c)[1]+rhs(_c)[2])/2, _p), sols); end if; return [0, sols]; end if; return results; end proc: # #Example: Katsura-6 # #Input data # F:=[x1+2*x2+2*x3+2*x4+2*x5+2*x6-1, # x1^2+2*x2^2+2*x3^2+2*x4^2+2*x5^2+2*x6^2-x1, # 2*x1*x2+2*x2*x3+2*x3*x4+2*x4*x5+2*x5*x6-x2, # x2^2+2*x1*x3+2*x2*x4+2*x3*x5+2*x4*x6-x3, # 2*x2*x3+2*x1*x4+2*x2*x5+2*x3*x6-x4, # x3^2+2*x2*x4+2*x1*x5+2*x2*x6-x5]; # vars:=[x1,x2,x3,x4,x5,x6]; # #Usage # #with rational parametrization # param, sols:=MSolveRealRoots(F,vars,"../binary/msolve","/tmp/in.ms","/tmp/out.ms",1); # #or with solutions only # sols:=MSolveRealRoots(F,vars); msolve-0.6.5/interfaces/msolve-to-maple-file-interface.mpl000066400000000000000000000263141456710632100235730ustar00rootroot00000000000000# /* This file is part of msolve. # * # * msolve 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. # * # * msolve 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 msolve. If not, see # * # * Authors: # * Christian Eder # * Jorge Garcia Fontan # * Huu Phuoc Le # * Mohab Safey El Din */ #WARNING: this file uses a sed command which does not work for mac users #Mac users should use the msolve-to-maple-file-interface-macos.mpl file FormatOutputMSolve:=proc(ll, _Z) local dim, deg, degquot, params, nvars, elim, den, cfs, i, varstr, linearform: dim:=ll[1]: if dim > 0 then return -1, [], []; fi; nvars:=ll[2]: degquot:=ll[3]: varstr:=ll[4]: linearform:=ll[5]: deg:=ll[6][1]: if nops(ll[6]) > 0 then elim:=PolynomialTools[FromCoefficientList](ll[6][2],_Z); else #computation failed return -2, [], []; fi: if nops(ll[5]) > 0 then den:=PolynomialTools[FromCoefficientList](ll[7][2],_Z); fi: params:=[]: cfs:=[1]: if degquot > 0 then for i from 1 to nvars-1 do params:=[op(params), PolynomialTools[FromCoefficientList](ll[8][i][1][2],_Z)]: cfs:=[op(cfs), ll[8][i][2]]: od: fi: return varstr, linearform, elim, den, [diff(elim, _Z), op(params)], cfs; end: GetRootsFromMSolve:=proc(l) local _Z, e, d, p, c, v, lf, sols, vals, i, sols_and_vals, realroots, OldDigits, mysols; local exist_gcd_p_e_nontrivial, length_p, gcd_p_e; v, lf, e, d, p, c := FormatOutputMSolve(l, _Z); if degree(e) = 0 then #positive dimension (-1) or computation failed (-2) return e, []; else return 0, [v,lf,e,d,p,c]; fi: end proc: ToMSolve:=proc(F, char, vars, fname) local i, fd, F2, str; fd:=fopen(fname, WRITE): for i from 1 to nops(vars)-1 do fprintf(fd, "%a, ", vars[i]): end; fprintf(fd, "%a ", vars[nops(vars)]): fprintf(fd,"\n"); fprintf(fd,"%d\n", char); if char = 0 then F2:=map(f->sort(expand(numer(f)), order=tdeg(op(vars))), F): F2:=remove(member, F2, [0]): for i from 1 to nops(F2)-1 do fprintf(fd, "%a,\n", F2[i]): od: fprintf(fd, "%a\n", F2[nops(F2)]): else F2:=map(f->sort(expand(numer(f)), order=tdeg(op(vars))) mod char, F): F2:=remove(member, F2, [0]): for i from 1 to nops(F2)-1 do fprintf(fd, "%a,\n", F2[i]): od: fprintf(fd, "%a\n", F2[nops(F2)]): fi: fclose(fd): str := cat("sed -i -e ':a' -e 'N' -e '$!ba' -e 's/\\\\\\n//g' ", fname): # str := cat("sed -i '' -e ':a' -e 'N' -e '$!ba' -e 's/\\\\\\n//g' ", fname): system(str): end proc: GetOptions:=proc(opts) local str, msolve_path, fname1, fname2, file_dir, verb, param, nthreads, output, gb; str:=subs(opts,"verb"); if type(str, integer) then verb:=str; else verb:=0: end if; str:=subs(opts,"leadmons"); if type(str, integer) and str > 0 then gb:=str; else gb:=2: end if; str:=subs(opts,"elim"); if type(str, integer) and str > 0 then elim:=str; else elim:=0: end if; str:=subs(opts,"output"); if type(str, integer) then output:=str; else output:=0: end if; str:=subs(opts,"nthreads"); if type(str, integer) then nthreads:=str; else nthreads:=1: end if; if member("mspath", map(lhs, opts)) then str:=subs(opts, "mspath"); if type(str, string) then msolve_path:=str; else printf("Error in format options"); end if; else msolve_path := "../msolve"; end if; if member("file_dir", map(lhs, opts)) then str:=subs(opts, "file_dir"); if type(str, string) then file_dir:=str; else printf("Error in format options"); end if; else file_dir := "/tmp/"; end if; if member("file_in", map(lhs, opts)) then str:=subs(opts, "file_in"); if type(str, string) then fname1:=cat(file_dir,str); else printf("Error in format options"); end if; else fname1 := cat(file_dir, RandomTools[Generate](string(8,alpha)), ".ms");; end if; if member("file_out", map(lhs, opts)) then str:=subs(opts, "file_out"); if type(str, string) then fname2:=cat(file_dir,str); else printf("Error in format options"); end if; else fname2 := cat(file_dir, RandomTools[Generate](string(8,alpha)), ".ms");; end if; param:=0; msolve_path, fname1, fname2, file_dir, verb, param, nthreads, output, gb, elim; end proc; #Input. #F: list of polynomials with rational coefficients #fc: field characteristic #vars: list of variables #Optional argument: # {"mspath"=, # "verb"=, # "file_dir"=, # "file_in"=, # "file_out"=, # "leadmons"= <1 to get leading monomials only> # "elim"=} #Output. #[] -> an error occured during the computation #else returns a Groebner basis of the ideal generated by F for the # grevlex ordering over monomials involving variables in vars # with vars[1] > ... > vars[n] # if "leadmons"=1 is part of the third optional argument, then only # the leading monomials are returned MSolveGroebner:=proc(F, fc, vars, opts:={}) local results, dim, fname1, fname2, verb, param, msolve_path, file_dir, field_char, lsols, nl, i, gb, output, nthreads, str, elim; if type(F, list(polynom(rational))) = false then printf("First argument is not a list of polynomials with rational coefficients\n"); end if; if type(fc, integer)=true then if fc < 0 then error "Field characteristic cannot be negative"; end if; if fc > 0 and isprime(fc)=false then error "Field characteristic should be a prime number"; end if; if fc > 2^31 then error "Field characteristic is too large to be supported"; end if; if fc > 0 then field_char := fc; end if; else printf("Second argument should be a prime integer < 2^31\n"); end if; if not(indets(F) subset indets(vars)) then printf("Given variables do not match the variables in the input polynomials\n"); end if; msolve_path:="../msolve"; file_dir:="/tmp/"; fname1:=cat(file_dir, RandomTools[Generate](string(8,alpha)), ".ms"); fname2:=cat(file_dir, RandomTools[Generate](string(8,alpha)), ".ms"); while evalb(fname1=fname2) do fname2:=cat(RandomTools[Generate](string(8,alpha)), ".ms"); od: verb:=0; param:=0: nthreads:=1; output:=0; gb:=2; if nops(opts) > 0 then msolve_path, fname1, fname2, file_dir, verb, param, nthreads, output, gb, elim := GetOptions(opts); fi; ToMSolve(F, field_char, vars, fname1); str := cat(msolve_path, " -v ", verb, " -g ", gb, " -e ", elim, " -P ", param, " -t ", nthreads, " -f ", fname1, " -o ", fname2): try system(str): read(fname2): catch: printf("There has been an issue in msolve computation\n"); return []; end: results:=%: system(cat("rm ", fname2)); system(cat("rm ", fname1)); return results; end proc: #Input. #F: list of polynomials with rational coefficients #vars: list of variables #Optional argument: # {"mspath"=, # "verb"=, # "file_dir"=, # "file_in"=, # "file_out"=, # "output"= <1 to get mid points of isolating boxes>} #Output. #[] -> an error occured during the computation #[1] -> input system has infinitely many complex solutions #[-1, []] -> input polynomial system has no real solution #[0, [sols]] -> input polynomial system has finitely many complex solutions # sols is the list of real solutions given with isolating boxes with the following format # [vars[1] = [a1, b1], ..., vars[n] = [an,bn]] #if "output"=1 is part of the third (optional) argument output format is # [ vars[1] = (a1+b1)/2, ..., vars[n] = (an+bn)/2 ] MSolveRealRoots:=proc(F, vars, opts:={}) local results, dim, fname1, fname2, verb, param, msolve_path, file_dir, lsols, nl, i, j, gb, output, nthreads, str, sols, prec; if type(F, list(polynom(rational))) = false then printf("First argument is not a list of polynomials with rational coefficients\n"); end if; if not(indets(F) subset indets(vars)) then printf("Given variables do not match the variables in the input polynomials\n"); end if; msolve_path:="../msolve"; file_dir:="/tmp/"; fname1:=cat(file_dir, RandomTools[Generate](string(8,alpha)), ".ms"); fname2:=cat(file_dir, RandomTools[Generate](string(8,alpha)), ".ms"); while evalb(fname1=fname2) do fname2:=cat(RandomTools[Generate](string(8,alpha)), ".ms"); od: verb:=0; param:=0: nthreads:=1; output:=0; gb:=0; if nops(opts) > 0 then msolve_path, fname1, fname2, file_dir, verb, param, nthreads, output, gb := GetOptions(opts); fi; ToMSolve(F, 0, vars, fname1); if Digits <= 10 then prec:=128: else prec:= iquo(Digits/10)*128: fi: str := cat(msolve_path, " -v ", verb, " -P ", param, " -t ", nthreads, " -f ", fname1, " -o ", fname2): gb:=0; #Needed to avoid the user stops GB comp once a prime computation is done param:=0; try system(str): read(fname2): catch: printf("There has been an issue in msolve computation\n"); return []; end: results:=%: system(cat("rm ", fname2)); system(cat("rm ", fname1)); if nops(results) = 0 then printf("There has been an issue in msolve computation\n"); return []; end if; dim := results[1]; if dim = -1 then if verb >= 1 then printf("Algebraic set is empty\n"); end if; return [-1, []]; end if; if dim > 0 then if verb >= 1 then printf("Algebraic set has positive dimension\n"); end if; return [1]; end if; if dim = 0 then lsols := results[2]; nl := lsols[1]: sols:=[]: for i from 1 to nl do sols:=[op(sols), op(map(_p->[seq(vars[j] = _p[j], j=1..nops(vars))], lsols[i+1]))]; od: if output=1 then sols := map(_p->map(_c->lhs(_c)=(rhs(_c)[1]+rhs(_c)[2])/2, _p), sols); end if; return [0, sols]; end if; return results; end proc: # #Example: Katsura-6 # #Input data # F:=[x1+2*x2+2*x3+2*x4+2*x5+2*x6-1, # x1^2+2*x2^2+2*x3^2+2*x4^2+2*x5^2+2*x6^2-x1, # 2*x1*x2+2*x2*x3+2*x3*x4+2*x4*x5+2*x5*x6-x2, # x2^2+2*x1*x3+2*x2*x4+2*x3*x5+2*x4*x6-x3, # 2*x2*x3+2*x1*x4+2*x2*x5+2*x3*x6-x4, # x3^2+2*x2*x4+2*x1*x5+2*x2*x6-x5]; # vars:=[x1,x2,x3,x4,x5,x6]; # #Usage # #with rational parametrization # param, sols:=MSolveRealRoots(F,vars,"../binary/msolve","/tmp/in.ms","/tmp/out.ms",1); # #or with solutions only # sols:=MSolveRealRoots(F,vars); msolve-0.6.5/interfaces/msolve-to-sage-file-interface.sage000066400000000000000000000116171456710632100235430ustar00rootroot00000000000000""" 17/02/2021 Adapted from the maple interface written by Huu Phuoc Le and Jorge Garcia-Fontan. """ import os def ToMSolve(F, finput="/tmp/in.ms"): """Convert a system of sage polynomials into a msolve input file. Inputs : F (list of polynomials): system of polynomial to solve finput (string): name of the msolve input file. """ A = F[0].parent() assert all(A1 == A for A1 in map(parent,F)),\ "The polynomials in the system must belong to the same polynomial ring." variables, char = A.variable_names(), A.characteristic() s = (", ".join(variables) + " \n" + str(char) + "\n") B = A.change_ring(order = 'degrevlex') F2 = [ str(B(f)).replace(" ", "") for f in F ] if "0" in F2: F2.remove("0") s += ",\n".join(F2) + "\n" fd = open(finput, 'w') fd.write(s) fd.close() def FormatOutputMSolveOnlySolutions(foutput): """Convert a msolve output file into solutions Inputs : foutput (string): name of the msolve output file Output : The set of solutions computed by msolve. """ f = open(foutput,'r') s = f.read() s = s.replace("\n","").replace(":","") R = sage_eval(s) intervals = R[1][1] S = [] if len(intervals) > 0: nvars = len(intervals[0]) for sol in intervals: s = [] for i in range(nvars): s.append((sol[i][0]+sol[i][1])/2) S.append(s) return S def FormatOutputMSolve(foutput): """Convert a msolve output file into a rational parametrization Inputs : foutput (string): name of the msolve output file Output : A rational parametrization of the zero-dimensional ideal describing the solutions. Note : p[i] and c[i] stand for the (i+1)-th coordinate. """ f = open(foutput,'r') s = f.read() s = s.replace("\n","").replace(":","") R = sage_eval(s) A. = QQ[] # dimension dim = R[0] if dim > 0: return None, None, A(-1), None, None, None, None # parametrization nvars = R[1][1] qdim = R[1][2] varstr = R[1][3] linearform = R[1][4] elim = R[1][5][1][0] den = R[1][5][1][1] polys = R[1][5][1][2] # solutions intervals = R[2][1] # nvars, degquot, deg = L[1], L[2], L[5][0] # varstr = L[3] # linearform = L[4] if len(elim) > 0: pelim = A(elim[1]) else: return None, None, A(-2), None, None, None, None pden, p, c = A(1), [], [] if qdim > 0: pden = A(den[1]) for l in polys: p.append(A(l[0][1])) c.append( l[1] ) S = [] if len(intervals) > 0: for sol in intervals: s = [] for i in range(nvars): s.append((sol[i][0]+sol[i][1])/2) S.append(s) return [varstr, linearform, pelim, pden, p, c, S] def GetRootsFromMSolve(foutput, param): """Compute rational approximation roots from an msolve output file The rational number is chosen in the isolating interval to be the smallest in bitsize. Inputs : foutput (string): name of the msolve output file Output : b (integer): error code Qroots : list of rationals approximations of the roots """ if param == 1: varstr, linearform, elim, den, p, c, sols = FormatOutputMSolve(foutput) if elim.degree() == 0: return elim, [], [] return 0, [varstr, linearform, elim, den, p, c], sols else: sols = FormatOutputMSolveOnlySolutions(foutput) return 0, [], sols def MSolveRealRoots(F, fname1="/tmp/in.ms", fname2="/tmp/out.ms", mspath="../binary/msolve", v=0, p=1): """Computes the a rational approximation of the real roots of a system of sage polynomials using msolve. Inputs : F (list of polynomials): system of polynomials to solve fname1 (string): complete name of the msolve input file used fname2 (string): complete name of the msolve output file used mspath (string): path to the msolve binary v (in [0,1,2]): level of msolve verbosity Output : sols (list of lists): list of rational approximation roots to the system represented by F. """ ToMSolve(F, fname1) os.system(mspath +" -v " + str(v) +" -P " + str(p) + " -f " + fname1 + " -o " + fname2) b, param, sols = GetRootsFromMSolve(fname2,p) if b == -1: print("System has infinitely many complex solutions") return [] if b == -2: print("System not in generic position. You may add to your system") print("a random linear form of your variables and a new variable") return [] #New(s) variable(s) may have been introduced at the end, for genericity purposes. n = len(F[0].parent().gens()) if p == 0: return [ s[:n] for s in sols ] else: return param, [ s[:n] for s in sols ] msolve-0.6.5/m4/000077500000000000000000000000001456710632100133545ustar00rootroot00000000000000msolve-0.6.5/m4/ax_check_compile_flag.m4000066400000000000000000000040701456710632100200650ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # # Check whether the given FLAG works with the current language's compiler # or gives an error. (Warnings, however, are ignored) # # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on # success/failure. # # If EXTRA-FLAGS is defined, it is added to the current language's default # flags (e.g. CFLAGS) when the check is done. The check is thus made with # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to # force the compiler to issue an error when a bad flag is given. # # INPUT gives an alternative input source to AC_COMPILE_IFELSE. # # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 6 AC_DEFUN([AX_CHECK_COMPILE_FLAG], [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl ])dnl AX_CHECK_COMPILE_FLAGS msolve-0.6.5/m4/ax_count_cpus.m4000066400000000000000000000044041456710632100164720ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_count_cpus.html # =========================================================================== # # SYNOPSIS # # AX_COUNT_CPUS # # DESCRIPTION # # Attempt to count the number of processors present on the machine. If the # detection fails, then a value of 1 is assumed. # # The value is placed in the CPU_COUNT variable. # # LICENSE # # Copyright (c) 2014 Karlson2k (Evgeny Grin) # Copyright (c) 2012 Brian Aker # Copyright (c) 2008 Michael Paul Bailey # Copyright (c) 2008 Christophe Tournayre # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 11 AC_DEFUN([AX_COUNT_CPUS],[ AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_PROG_EGREP]) AC_MSG_CHECKING([the number of available CPUs]) CPU_COUNT="0" AS_CASE([$host_os],[ *darwin*],[ AS_IF([test -x /usr/sbin/sysctl],[ sysctl_a=`/usr/sbin/sysctl -a 2>/dev/null| grep -c hw.cpu` AS_IF([test sysctl_a],[ CPU_COUNT=`/usr/sbin/sysctl -n hw.ncpu` ]) ])],[ *linux*],[ AS_IF([test "x$CPU_COUNT" = "x0" -a -e /proc/cpuinfo],[ AS_IF([test "x$CPU_COUNT" = "x0" -a -e /proc/cpuinfo],[ CPU_COUNT=`$EGREP -c '^processor' /proc/cpuinfo` ]) ])],[ *mingw*],[ AS_IF([test -n "$NUMBER_OF_PROCESSORS"],[ CPU_COUNT="$NUMBER_OF_PROCESSORS" ])],[ *cygwin*],[ AS_IF([test -n "$NUMBER_OF_PROCESSORS"],[ CPU_COUNT="$NUMBER_OF_PROCESSORS" ]) ]) AS_IF([test "x$CPU_COUNT" = "x0"],[ CPU_COUNT="1" AC_MSG_RESULT( [unable to detect (assuming 1)] ) AC_DEFINE_UNQUOTED(NUMBER_OF_CPUS, ${CPU_COUNT},[Number of CPUs, test failed, set to one.]) ],[ AC_MSG_RESULT( $CPU_COUNT ) AC_DEFINE_UNQUOTED(NUMBER_OF_CPUS, ${CPU_COUNT},[Number of CPUs.]) ]) ]) msolve-0.6.5/m4/ax_cpu_vendor.m4000066400000000000000000000027111456710632100164530ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_cpu_vendor.html # =========================================================================== # # SYNOPSIS # # AX_CPU_VENDOR # # DESCRIPTION # # Find your CPU's vendor by requesting cpuid and define "ax_cpu_vendor" # accordingly. This macro depends on AX_GCC_X86_CPUID. # # LICENSE # # Copyright (c) 2008 Christophe Tournayre # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 7 AC_DEFUN([AX_CPU_VENDOR], [ AC_REQUIRE([AX_GCC_X86_CPUID]) AX_GCC_X86_CPUID(0x0) AC_CACHE_CHECK(for the processor vendor, ax_cpu_vendor, [ vendor=`echo $ax_cv_gcc_x86_cpuid_0x0 | cut -d ":" -f 2` case $vendor in 756e6547*) ax_cpu_vendor="Intel" ;; 68747541*) ax_cpu_vendor="AMD" ;; 69727943*) ax_cpu_vendor="Cyrix" ;; 746e6543*) ax_cpu_vendor="IDT" ;; 646f6547*) ax_cpu_vendor="Natsemi Geode" ;; 52697365*) ax_cpu_vendor="Rise" ;; 65736952*) ax_cpu_vendor="Rise" ;; 20536953*) ax_cpu_vendor="SiS" ;; *) ax_cpu_vendor="Unknown" ;; esac ]) ]) msolve-0.6.5/m4/ax_ext.m4000066400000000000000000000361221456710632100151120ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_ext.html # =========================================================================== # # SYNOPSIS # # AX_EXT # # DESCRIPTION # # Find supported SIMD extensions by requesting cpuid. When a SIMD # extension is found, the -m"simdextensionname" is added to SIMD_FLAGS if # compiler supports it. For example, if "sse2" is available then "-msse2" # is added to SIMD_FLAGS. # # Find other supported CPU extensions by requesting cpuid. When a # processor extension is found, the -m"extensionname" is added to # CPUEXT_FLAGS if compiler supports it. For example, if "bmi2" is # available then "-mbmi2" is added to CPUEXT_FLAGS. # # This macro calls: # # AC_SUBST(SIMD_FLAGS) # AC_SUBST(CPUEXT_FLAGS) # # And defines: # # HAVE_RDRND / HAVE_BMI1 / HAVE_BMI2 / HAVE_ADX / HAVE_MPX # HAVE_PREFETCHWT1 / HAVE_ABM / HAVE_MMX / HAVE_SSE / HAVE_SSE2 # HAVE_SSE3 / HAVE_SSSE3 / HAVE_SSE4_1 / HAVE_SSE4_2 / HAVE_SSE4a # HAVE_SHA / HAVE_AES / HAVE_AVX / HAVE_FMA3 / HAVE_FMA4 / HAVE_XOP # HAVE_AVX2 / HAVE_AVX512_F / HAVE_AVX512_CD / HAVE_AVX512_PF # HAVE_AVX512_ER / HAVE_AVX512_VL / HAVE_AVX512_BW / HAVE_AVX512_DQ # HAVE_AVX512_IFMA / HAVE_AVX512_VBMI / HAVE_ALTIVEC / HAVE_VSX # # LICENSE # # Copyright (c) 2007 Christophe Tournayre # Copyright (c) 2013,2015 Michael Petch # Copyright (c) 2017 Rafael de Lucena Valle # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 18 AC_DEFUN([AX_EXT], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_PROG_CC]) CPUEXT_FLAGS="" SIMD_FLAGS="" case $host_cpu in powerpc*) AC_CACHE_CHECK([whether altivec is supported for old distros], [ax_cv_have_altivec_old_ext], [ if test `/usr/sbin/sysctl -a 2>/dev/null| grep -c hw.optional.altivec` != 0; then if test `/usr/sbin/sysctl -n hw.optional.altivec` = 1; then ax_cv_have_altivec_old_ext=yes fi fi ]) if test "$ax_cv_have_altivec_old_ext" = yes; then AC_DEFINE(HAVE_ALTIVEC,,[Support Altivec instructions]) AX_CHECK_COMPILE_FLAG(-faltivec, SIMD_FLAGS="$SIMD_FLAGS -faltivec", []) fi AC_CACHE_CHECK([whether altivec is supported], [ax_cv_have_altivec_ext], [ if test `LD_SHOW_AUXV=1 /bin/true 2>/dev/null|grep -c altivec` != 0; then ax_cv_have_altivec_ext=yes fi ]) if test "$ax_cv_have_altivec_ext" = yes; then AC_DEFINE(HAVE_ALTIVEC,,[Support Altivec instructions]) AX_CHECK_COMPILE_FLAG(-maltivec, SIMD_FLAGS="$SIMD_FLAGS -maltivec", []) fi AC_CACHE_CHECK([whether vsx is supported], [ax_cv_have_vsx_ext], [ if test `LD_SHOW_AUXV=1 /bin/true 2>/dev/null|grep -c vsx` != 0; then ax_cv_have_vsx_ext=yes fi ]) if test "$ax_cv_have_vsx_ext" = yes; then AC_DEFINE(HAVE_VSX,,[Support VSX instructions]) AX_CHECK_COMPILE_FLAG(-mvsx, SIMD_FLAGS="$SIMD_FLAGS -mvsx", []) fi ;; i[[3456]]86*|x86_64*|amd64*) AC_REQUIRE([AX_GCC_X86_CPUID]) AC_REQUIRE([AX_GCC_X86_CPUID_COUNT]) AC_REQUIRE([AX_GCC_X86_AVX_XGETBV]) eax_cpuid0=0 AX_GCC_X86_CPUID(0x00000000) if test "$ax_cv_gcc_x86_cpuid_0x00000000" != "unknown"; then eax_cpuid0=`echo $ax_cv_gcc_x86_cpuid_0x00000000 | cut -d ":" -f 1` fi eax_cpuid80000000=0 AX_GCC_X86_CPUID(0x80000000) if test "$ax_cv_gcc_x86_cpuid_0x80000000" != "unknown"; then eax_cpuid80000000=`echo $ax_cv_gcc_x86_cpuid_0x80000000 | cut -d ":" -f 1` fi ecx_cpuid1=0 edx_cpuid1=0 if test "$((0x$eax_cpuid0))" -ge 1 ; then AX_GCC_X86_CPUID(0x00000001) if test "$ax_cv_gcc_x86_cpuid_0x00000001" != "unknown"; then ecx_cpuid1=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | cut -d ":" -f 3` edx_cpuid1=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | cut -d ":" -f 4` fi fi ebx_cpuid7=0 ecx_cpuid7=0 if test "$((0x$eax_cpuid0))" -ge 7 ; then AX_GCC_X86_CPUID_COUNT(0x00000007, 0x00) if test "$ax_cv_gcc_x86_cpuid_0x00000007" != "unknown"; then ebx_cpuid7=`echo $ax_cv_gcc_x86_cpuid_0x00000007 | cut -d ":" -f 2` ecx_cpuid7=`echo $ax_cv_gcc_x86_cpuid_0x00000007 | cut -d ":" -f 3` fi fi ecx_cpuid80000001=0 edx_cpuid80000001=0 if test "$((0x$eax_cpuid80000000))" -ge "$((0x80000001))" ; then AX_GCC_X86_CPUID(0x80000001) if test "$ax_cv_gcc_x86_cpuid_0x80000001" != "unknown"; then ecx_cpuid80000001=`echo $ax_cv_gcc_x86_cpuid_0x80000001 | cut -d ":" -f 3` edx_cpuid80000001=`echo $ax_cv_gcc_x86_cpuid_0x80000001 | cut -d ":" -f 4` fi fi AC_CACHE_VAL([ax_cv_have_mmx_os_support_ext], [ ax_cv_have_mmx_os_support_ext=yes ]) ax_cv_have_none_os_support_ext=yes AC_CACHE_VAL([ax_cv_have_sse_os_support_ext], [ ax_cv_have_sse_os_support_ext=no, if test "$((0x$edx_cpuid1>>25&0x01))" = 1; then AC_LANG_PUSH([C]) AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include /* No way at ring1 to ring3 in protected mode to check the CR0 and CR4 control registers directly. Execute an SSE instruction. If it raises SIGILL then OS doesn't support SSE based instructions */ void sig_handler(int signum){ exit(1); } int main(){ signal(SIGILL, sig_handler); /* SSE instruction xorps %xmm0,%xmm0 */ __asm__ __volatile__ (".byte 0x0f, 0x57, 0xc0"); return 0; }]])], [ax_cv_have_sse_os_support_ext=yes], [ax_cv_have_sse_os_support_ext=no], [ax_cv_have_sse_os_support_ext=no]) AC_LANG_POP([C]) fi ]) xgetbv_eax=0 if test "$((0x$ecx_cpuid1>>28&0x01))" = 1; then AX_GCC_X86_AVX_XGETBV(0x00000000) if test x"$ax_cv_gcc_x86_avx_xgetbv_0x00000000" != x"unknown"; then xgetbv_eax=`echo $ax_cv_gcc_x86_avx_xgetbv_0x00000000 | cut -d ":" -f 1` fi AC_CACHE_VAL([ax_cv_have_avx_os_support_ext], [ ax_cv_have_avx_os_support_ext=no if test "$((0x$ecx_cpuid1>>27&0x01))" = 1; then if test "$((0x$xgetbv_eax&0x6))" = 6; then ax_cv_have_avx_os_support_ext=yes fi fi ]) fi AC_CACHE_VAL([ax_cv_have_avx512_os_support_ext], [ ax_cv_have_avx512_os_support_ext=no if test "$ax_cv_have_avx_os_support_ext" = yes; then if test "$((0x$xgetbv_eax&0xe6))" = "$((0xe6))"; then ax_cv_have_avx512_os_support_ext=yes fi fi ]) for ac_instr_info dnl in "none;rdrnd;RDRND;ecx_cpuid1,30;-mrdrnd;HAVE_RDRND;CPUEXT_FLAGS" dnl "none;bmi1;BMI1;ebx_cpuid7,3;-mbmi;HAVE_BMI1;CPUEXT_FLAGS" dnl "none;bmi2;BMI2;ebx_cpuid7,8;-mbmi2;HAVE_BMI2;CPUEXT_FLAGS" dnl "none;adx;ADX;ebx_cpuid7,19;-madx;HAVE_ADX;CPUEXT_FLAGS" dnl dnl "none;mpx;MPX;ebx_cpuid7,14;-mmpx;HAVE_MPX;CPUEXT_FLAGS" dnl "none;prefetchwt1;PREFETCHWT1;ecx_cpuid7,0;-mprefetchwt1;HAVE_PREFETCHWT1;CPUEXT_FLAGS" dnl "none;abm;ABM;ecx_cpuid80000001,5;-mabm;HAVE_ABM;CPUEXT_FLAGS" dnl "mmx;mmx;MMX;edx_cpuid1,23;-mmmx;HAVE_MMX;SIMD_FLAGS" dnl "sse;sse;SSE;edx_cpuid1,25;-msse;HAVE_SSE;SIMD_FLAGS" dnl "sse;sse2;SSE2;edx_cpuid1,26;-msse2;HAVE_SSE2;SIMD_FLAGS" dnl "sse;sse3;SSE3;ecx_cpuid1,1;-msse3;HAVE_SSE3;SIMD_FLAGS" dnl "sse;ssse3;SSSE3;ecx_cpuid1,9;-mssse3;HAVE_SSSE3;SIMD_FLAGS" dnl "sse;sse41;SSE4.1;ecx_cpuid1,19;-msse4.1;HAVE_SSE4_1;SIMD_FLAGS" dnl "sse;sse42;SSE4.2;ecx_cpuid1,20;-msse4.2;HAVE_SSE4_2;SIMD_FLAGS" dnl "sse;sse4a;SSE4a;ecx_cpuid80000001,6;-msse4a;HAVE_SSE4a;SIMD_FLAGS" dnl "sse;sha;SHA;ebx_cpuid7,29;-msha;HAVE_SHA;SIMD_FLAGS" dnl "sse;aes;AES;ecx_cpuid1,25;-maes;HAVE_AES;SIMD_FLAGS" dnl "avx;avx;AVX;ecx_cpuid1,28;-mavx;HAVE_AVX;SIMD_FLAGS" dnl "avx;fma3;FMA3;ecx_cpuid1,12;-mfma;HAVE_FMA3;SIMD_FLAGS" dnl "avx;fma4;FMA4;ecx_cpuid80000001,16;-mfma4;HAVE_FMA4;SIMD_FLAGS" dnl "avx;xop;XOP;ecx_cpuid80000001,11;-mxop;HAVE_XOP;SIMD_FLAGS" dnl "avx;avx2;AVX2;ebx_cpuid7,5;-mavx2;HAVE_AVX2;SIMD_FLAGS" dnl "avx512;avx512f;AVX512-F;ebx_cpuid7,16;-mavx512f;HAVE_AVX512_F;SIMD_FLAGS" dnl "avx512;avx512cd;AVX512-CD;ebx_cpuid7,28;-mavx512cd;HAVE_AVX512_CD;SIMD_FLAGS" dnl "avx512;avx512pf;AVX512-PF;ebx_cpuid7,26;-mavx512pf;HAVE_AVX512_PF;SIMD_FLAGS" dnl "avx512;avx512er;AVX512-ER;ebx_cpuid7,27;-mavx512er;HAVE_AVX512_ER;SIMD_FLAGS" dnl "avx512;avx512vl;AVX512-VL;ebx_cpuid7,31;-mavx512vl;HAVE_AVX512_VL;SIMD_FLAGS" dnl "avx512;avx512bw;AVX512-BW;ebx_cpuid7,30;-mavx512bw;HAVE_AVX512_BW;SIMD_FLAGS" dnl "avx512;avx512dq;AVX512-DQ;ebx_cpuid7,17;-mavx512dq;HAVE_AVX512_DQ;SIMD_FLAGS" dnl "avx512;avx512ifma;AVX512-IFMA;ebx_cpuid7,21;-mavx512ifma;HAVE_AVX512_IFMA;SIMD_FLAGS" dnl "avx512;avx512vbmi;AVX512-VBMI;ecx_cpuid7,1;-mavx512vbmi;HAVE_AVX512_VBMI;SIMD_FLAGS" dnl # do ac_instr_os_support=$(eval echo \$ax_cv_have_$(echo $ac_instr_info | cut -d ";" -f 1)_os_support_ext) ac_instr_acvar=$(echo $ac_instr_info | cut -d ";" -f 2) ac_instr_shortname=$(echo $ac_instr_info | cut -d ";" -f 3) ac_instr_chk_loc=$(echo $ac_instr_info | cut -d ";" -f 4) ac_instr_chk_reg=0x$(eval echo \$$(echo $ac_instr_chk_loc | cut -d "," -f 1)) ac_instr_chk_bit=$(echo $ac_instr_chk_loc | cut -d "," -f 2) ac_instr_compiler_flags=$(echo $ac_instr_info | cut -d ";" -f 5) ac_instr_have_define=$(echo $ac_instr_info | cut -d ";" -f 6) ac_instr_flag_type=$(echo $ac_instr_info | cut -d ";" -f 7) AC_CACHE_CHECK([whether ${ac_instr_shortname} is supported by the processor], [ax_cv_have_${ac_instr_acvar}_cpu_ext], [ eval ax_cv_have_${ac_instr_acvar}_cpu_ext=no if test "$((${ac_instr_chk_reg}>>${ac_instr_chk_bit}&0x01))" = 1 ; then eval ax_cv_have_${ac_instr_acvar}_cpu_ext=yes fi ]) if test x"$(eval echo \$ax_cv_have_${ac_instr_acvar}_cpu_ext)" = x"yes"; then AC_CACHE_CHECK([whether ${ac_instr_shortname} is supported by the processor and OS], [ax_cv_have_${ac_instr_acvar}_ext], [ eval ax_cv_have_${ac_instr_acvar}_ext=no if test x"${ac_instr_os_support}" = x"yes"; then eval ax_cv_have_${ac_instr_acvar}_ext=yes fi ]) if test "$(eval echo \$ax_cv_have_${ac_instr_acvar}_ext)" = yes; then AX_CHECK_COMPILE_FLAG(${ac_instr_compiler_flags}, eval ax_cv_support_${ac_instr_acvar}_ext=yes, eval ax_cv_support_${ac_instr_acvar}_ext=no) if test x"$(eval echo \$ax_cv_support_${ac_instr_acvar}_ext)" = x"yes"; then eval ${ac_instr_flag_type}=\"\$${ac_instr_flag_type} ${ac_instr_compiler_flags}\" AC_DEFINE_UNQUOTED([${ac_instr_have_define}]) else AC_MSG_WARN([Your processor and OS supports ${ac_instr_shortname} instructions but not your compiler, can you try another compiler?]) fi else if test x"${ac_instr_os_support}" = x"no"; then AC_CACHE_VAL(ax_cv_support_${ac_instr_acvar}_ext, eval ax_cv_support_${ac_instr_acvar}_ext=no) AC_MSG_WARN([Your processor supports ${ac_instr_shortname}, but your OS doesn't]) fi fi else AC_CACHE_VAL(ax_cv_have_${ac_instr_acvar}_ext, eval ax_cv_have_${ac_instr_acvar}_ext=no) AC_CACHE_VAL(ax_cv_support_${ac_instr_acvar}_ext, eval ax_cv_support_${ac_instr_acvar}_ext=no) fi done ;; esac AH_TEMPLATE([HAVE_RDRND],[Define to 1 to support Digital Random Number Generator]) AH_TEMPLATE([HAVE_BMI1],[Define to 1 to support Bit Manipulation Instruction Set 1]) AH_TEMPLATE([HAVE_BMI2],[Define to 1 to support Bit Manipulation Instruction Set 2]) AH_TEMPLATE([HAVE_ADX],[Define to 1 to support Multi-Precision Add-Carry Instruction Extensions]) AH_TEMPLATE([HAVE_MPX],[Define to 1 to support Memory Protection Extensions]) AH_TEMPLATE([HAVE_PREFETCHWT1],[Define to 1 to support Prefetch Vector Data Into Caches WT1]) AH_TEMPLATE([HAVE_ABM],[Define to 1 to support Advanced Bit Manipulation]) AH_TEMPLATE([HAVE_MMX],[Define to 1 to support Multimedia Extensions]) AH_TEMPLATE([HAVE_SSE],[Define to 1 to support Streaming SIMD Extensions]) AH_TEMPLATE([HAVE_SSE2],[Define to 1 to support Streaming SIMD Extensions]) AH_TEMPLATE([HAVE_SSE3],[Define to 1 to support Streaming SIMD Extensions 3]) AH_TEMPLATE([HAVE_SSSE3],[Define to 1 to support Supplemental Streaming SIMD Extensions 3]) AH_TEMPLATE([HAVE_SSE4_1],[Define to 1 to support Streaming SIMD Extensions 4.1]) AH_TEMPLATE([HAVE_SSE4_2],[Define to 1 to support Streaming SIMD Extensions 4.2]) AH_TEMPLATE([HAVE_SSE4a],[Define to 1 to support AMD Streaming SIMD Extensions 4a]) AH_TEMPLATE([HAVE_SHA],[Define to 1 to support Secure Hash Algorithm Extension]) AH_TEMPLATE([HAVE_AES],[Define to 1 to support Advanced Encryption Standard New Instruction Set (AES-NI)]) AH_TEMPLATE([HAVE_AVX],[Define to 1 to support Advanced Vector Extensions]) AH_TEMPLATE([HAVE_FMA3],[Define to 1 to support Fused Multiply-Add Extensions 3]) AH_TEMPLATE([HAVE_FMA4],[Define to 1 to support Fused Multiply-Add Extensions 4]) AH_TEMPLATE([HAVE_XOP],[Define to 1 to support eXtended Operations Extensions]) AH_TEMPLATE([HAVE_AVX2],[Define to 1 to support Advanced Vector Extensions 2]) AH_TEMPLATE([HAVE_AVX512_F],[Define to 1 to support AVX-512 Foundation Extensions]) AH_TEMPLATE([HAVE_AVX512_CD],[Define to 1 to support AVX-512 Conflict Detection Instructions]) AH_TEMPLATE([HAVE_AVX512_PF],[Define to 1 to support AVX-512 Conflict Prefetch Instructions]) AH_TEMPLATE([HAVE_AVX512_ER],[Define to 1 to support AVX-512 Exponential & Reciprocal Instructions]) AH_TEMPLATE([HAVE_AVX512_VL],[Define to 1 to support AVX-512 Vector Length Extensions]) AH_TEMPLATE([HAVE_AVX512_BW],[Define to 1 to support AVX-512 Byte and Word Instructions]) AH_TEMPLATE([HAVE_AVX512_DQ],[Define to 1 to support AVX-512 Doubleword and Quadword Instructions]) AH_TEMPLATE([HAVE_AVX512_IFMA],[Define to 1 to support AVX-512 Integer Fused Multiply Add Instructions]) AH_TEMPLATE([HAVE_AVX512_VBMI],[Define to 1 to support AVX-512 Vector Byte Manipulation Instructions]) AC_SUBST(SIMD_FLAGS) AC_SUBST(CPUEXT_FLAGS) ]) msolve-0.6.5/m4/ax_gcc_builtin.m4000066400000000000000000000132371456710632100165760ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_gcc_builtin.html # =========================================================================== # # SYNOPSIS # # AX_GCC_BUILTIN(BUILTIN) # # DESCRIPTION # # This macro checks if the compiler supports one of GCC's built-in # functions; many other compilers also provide those same built-ins. # # The BUILTIN parameter is the name of the built-in function. # # If BUILTIN is supported define HAVE_. Keep in mind that since # builtins usually start with two underscores they will be copied over # into the HAVE_ definition (e.g. HAVE___BUILTIN_EXPECT for # __builtin_expect()). # # The macro caches its result in the ax_cv_have_ variable (e.g. # ax_cv_have___builtin_expect). # # The macro currently supports the following built-in functions: # # __builtin_assume_aligned # __builtin_bswap32 # __builtin_bswap64 # __builtin_choose_expr # __builtin___clear_cache # __builtin_clrsb # __builtin_clrsbl # __builtin_clrsbll # __builtin_clz # __builtin_clzl # __builtin_clzll # __builtin_complex # __builtin_constant_p # __builtin_ctz # __builtin_ctzl # __builtin_ctzll # __builtin_expect # __builtin_ffs # __builtin_ffsl # __builtin_ffsll # __builtin_fpclassify # __builtin_huge_val # __builtin_huge_valf # __builtin_huge_vall # __builtin_inf # __builtin_infd128 # __builtin_infd32 # __builtin_infd64 # __builtin_inff # __builtin_infl # __builtin_isinf_sign # __builtin_nan # __builtin_nand128 # __builtin_nand32 # __builtin_nand64 # __builtin_nanf # __builtin_nanl # __builtin_nans # __builtin_nansf # __builtin_nansl # __builtin_object_size # __builtin_parity # __builtin_parityl # __builtin_parityll # __builtin_popcount # __builtin_popcountl # __builtin_popcountll # __builtin_powi # __builtin_powif # __builtin_powil # __builtin_prefetch # __builtin_trap # __builtin_types_compatible_p # __builtin_unreachable # # Unsuppored built-ins will be tested with an empty parameter set and the # result of the check might be wrong or meaningless so use with care. # # LICENSE # # Copyright (c) 2013 Gabriele Svelto # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 2 AC_DEFUN([AX_GCC_BUILTIN], [ AS_VAR_PUSHDEF([ac_var], [ax_cv_have_$1]) AC_CACHE_CHECK([for $1], [ac_var], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([], [ m4_case([$1], [__builtin_assume_aligned], [$1("", 0)], [__builtin_bswap32], [$1(0)], [__builtin_bswap64], [$1(0)], [__builtin_choose_expr], [$1(0, 0, 0)], [__builtin___clear_cache], [$1("", "")], [__builtin_clrsb], [$1(0)], [__builtin_clrsbl], [$1(0)], [__builtin_clrsbll], [$1(0)], [__builtin_clz], [$1(0)], [__builtin_clzl], [$1(0)], [__builtin_clzll], [$1(0)], [__builtin_complex], [$1(0.0, 0.0)], [__builtin_constant_p], [$1(0)], [__builtin_ctz], [$1(0)], [__builtin_ctzl], [$1(0)], [__builtin_ctzll], [$1(0)], [__builtin_expect], [$1(0, 0)], [__builtin_ffs], [$1(0)], [__builtin_ffsl], [$1(0)], [__builtin_ffsll], [$1(0)], [__builtin_fpclassify], [$1(0, 1, 2, 3, 4, 0.0)], [__builtin_huge_val], [$1()], [__builtin_huge_valf], [$1()], [__builtin_huge_vall], [$1()], [__builtin_inf], [$1()], [__builtin_infd128], [$1()], [__builtin_infd32], [$1()], [__builtin_infd64], [$1()], [__builtin_inff], [$1()], [__builtin_infl], [$1()], [__builtin_isinf_sign], [$1(0.0)], [__builtin_nan], [$1("")], [__builtin_nand128], [$1("")], [__builtin_nand32], [$1("")], [__builtin_nand64], [$1("")], [__builtin_nanf], [$1("")], [__builtin_nanl], [$1("")], [__builtin_nans], [$1("")], [__builtin_nansf], [$1("")], [__builtin_nansl], [$1("")], [__builtin_object_size], [$1("", 0)], [__builtin_parity], [$1(0)], [__builtin_parityl], [$1(0)], [__builtin_parityll], [$1(0)], [__builtin_popcount], [$1(0)], [__builtin_popcountl], [$1(0)], [__builtin_popcountll], [$1(0)], [__builtin_powi], [$1(0, 0)], [__builtin_powif], [$1(0, 0)], [__builtin_powil], [$1(0, 0)], [__builtin_prefetch], [$1("")], [__builtin_trap], [$1()], [__builtin_types_compatible_p], [$1(int, int)], [__builtin_unreachable], [$1()], [m4_warn([syntax], [Unsupported built-in $1, the test may fail]) $1()] ) ])], [AS_VAR_SET([ac_var], [yes])], [AS_VAR_SET([ac_var], [no])]) ]) AS_IF([test yes = AS_VAR_GET([ac_var])], [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$1), 1, [Define to 1 if the system has the `$1' built-in function])], []) AS_VAR_POPDEF([ac_var]) ]) msolve-0.6.5/m4/ax_gcc_x86_avx_xgetbv.m4000066400000000000000000000064221456710632100200100ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_gcc_x86_avx_xgetbv.html # =========================================================================== # # SYNOPSIS # # AX_GCC_X86_AVX_XGETBV # # DESCRIPTION # # On later x86 processors with AVX SIMD support, with gcc or a compiler # that has a compatible syntax for inline assembly instructions, run a # small program that executes the xgetbv instruction with input OP. This # can be used to detect if the OS supports AVX instruction usage. # # On output, the values of the eax and edx registers are stored as # hexadecimal strings as "eax:edx" in the cache variable # ax_cv_gcc_x86_avx_xgetbv. # # If the xgetbv instruction fails (because you are running a # cross-compiler, or because you are not using gcc, or because you are on # a processor that doesn't have this instruction), # ax_cv_gcc_x86_avx_xgetbv_OP is set to the string "unknown". # # This macro mainly exists to be used in AX_EXT. # # LICENSE # # Copyright (c) 2013 Michael Petch # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 3 AC_DEFUN([AX_GCC_X86_AVX_XGETBV], [AC_REQUIRE([AC_PROG_CC]) AC_LANG_PUSH([C]) AC_CACHE_CHECK(for x86-AVX xgetbv $1 output, ax_cv_gcc_x86_avx_xgetbv_$1, [AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], [ int op = $1, eax, edx; FILE *f; /* Opcodes for xgetbv */ __asm__ __volatile__ (".byte 0x0f, 0x01, 0xd0" : "=a" (eax), "=d" (edx) : "c" (op)); f = fopen("conftest_xgetbv", "w"); if (!f) return 1; fprintf(f, "%x:%x\n", eax, edx); fclose(f); return 0; ])], [ax_cv_gcc_x86_avx_xgetbv_$1=`cat conftest_xgetbv`; rm -f conftest_xgetbv], [ax_cv_gcc_x86_avx_xgetbv_$1=unknown; rm -f conftest_xgetbv], [ax_cv_gcc_x86_avx_xgetbv_$1=unknown])]) AC_LANG_POP([C]) ]) msolve-0.6.5/m4/ax_gcc_x86_cpuid.m4000066400000000000000000000071671456710632100167460ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_gcc_x86_cpuid.html # =========================================================================== # # SYNOPSIS # # AX_GCC_X86_CPUID(OP) # AX_GCC_X86_CPUID_COUNT(OP, COUNT) # # DESCRIPTION # # On Pentium and later x86 processors, with gcc or a compiler that has a # compatible syntax for inline assembly instructions, run a small program # that executes the cpuid instruction with input OP. This can be used to # detect the CPU type. AX_GCC_X86_CPUID_COUNT takes an additional COUNT # parameter that gets passed into register ECX before calling cpuid. # # On output, the values of the eax, ebx, ecx, and edx registers are stored # as hexadecimal strings as "eax:ebx:ecx:edx" in the cache variable # ax_cv_gcc_x86_cpuid_OP. # # If the cpuid instruction fails (because you are running a # cross-compiler, or because you are not using gcc, or because you are on # a processor that doesn't have this instruction), ax_cv_gcc_x86_cpuid_OP # is set to the string "unknown". # # This macro mainly exists to be used in AX_GCC_ARCHFLAG. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2008 Matteo Frigo # Copyright (c) 2015 Michael Petch # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 10 AC_DEFUN([AX_GCC_X86_CPUID], [AX_GCC_X86_CPUID_COUNT($1, 0) ]) AC_DEFUN([AX_GCC_X86_CPUID_COUNT], [AC_REQUIRE([AC_PROG_CC]) AC_LANG_PUSH([C]) AC_CACHE_CHECK(for x86 cpuid $1 output, ax_cv_gcc_x86_cpuid_$1, [AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], [ int op = $1, level = $2, eax, ebx, ecx, edx; FILE *f; __asm__ __volatile__ ("xchg %%ebx, %1\n" "cpuid\n" "xchg %%ebx, %1\n" : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) : "a" (op), "2" (level)); f = fopen("conftest_cpuid", "w"); if (!f) return 1; fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx); fclose(f); return 0; ])], [ax_cv_gcc_x86_cpuid_$1=`cat conftest_cpuid`; rm -f conftest_cpuid], [ax_cv_gcc_x86_cpuid_$1=unknown; rm -f conftest_cpuid], [ax_cv_gcc_x86_cpuid_$1=unknown])]) AC_LANG_POP([C]) ]) msolve-0.6.5/m4/ax_openmp.m4000066400000000000000000000112141456710632100156030ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_openmp.html # =========================================================================== # # SYNOPSIS # # AX_OPENMP([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro tries to find out how to compile programs that use OpenMP a # standard API and set of compiler directives for parallel programming # (see http://www-unix.mcs/) # # On success, it sets the OPENMP_CFLAGS/OPENMP_CXXFLAGS/OPENMP_F77FLAGS # output variable to the flag (e.g. -omp) used both to compile *and* link # OpenMP programs in the current language. # # NOTE: You are assumed to not only compile your program with these flags, # but also link it with them as well. # # If you want to compile everything with OpenMP, you should set: # # CFLAGS="$CFLAGS $OPENMP_CFLAGS" # #OR# CXXFLAGS="$CXXFLAGS $OPENMP_CXXFLAGS" # #OR# FFLAGS="$FFLAGS $OPENMP_FFLAGS" # # (depending on the selected language). # # The user can override the default choice by setting the corresponding # environment variable (e.g. OPENMP_CFLAGS). # # ACTION-IF-FOUND is a list of shell commands to run if an OpenMP flag is # found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it is # not found. If ACTION-IF-FOUND is not specified, the default action will # define HAVE_OPENMP. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2015 John W. Peterson # Copyright (c) 2016 Nick R. Papior # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 13 AC_DEFUN([AX_OPENMP], [ AC_PREREQ([2.69]) dnl for _AC_LANG_PREFIX AC_CACHE_CHECK([for OpenMP flag of _AC_LANG compiler], ax_cv_[]_AC_LANG_ABBREV[]_openmp, [save[]_AC_LANG_PREFIX[]FLAGS=$[]_AC_LANG_PREFIX[]FLAGS ax_cv_[]_AC_LANG_ABBREV[]_openmp=unknown # Flags to try: -fopenmp (gcc), -mp (SGI & PGI), # -qopenmp (icc>=15), -openmp (icc), # -xopenmp (Sun), -omp (Tru64), # -qsmp=omp (AIX), # none ax_openmp_flags="-fopenmp -openmp -qopenmp -mp -xopenmp -omp -qsmp=omp none" if test "x$OPENMP_[]_AC_LANG_PREFIX[]FLAGS" != x; then ax_openmp_flags="$OPENMP_[]_AC_LANG_PREFIX[]FLAGS $ax_openmp_flags" fi for ax_openmp_flag in $ax_openmp_flags; do case $ax_openmp_flag in none) []_AC_LANG_PREFIX[]FLAGS=$save[]_AC_LANG_PREFIX[] ;; *) []_AC_LANG_PREFIX[]FLAGS="$save[]_AC_LANG_PREFIX[]FLAGS $ax_openmp_flag" ;; esac AC_LINK_IFELSE([AC_LANG_SOURCE([[ @%:@include static void parallel_fill(int * data, int n) { int i; @%:@pragma omp parallel for for (i = 0; i < n; ++i) data[i] = i; } int main() { int arr[100000]; omp_set_num_threads(2); parallel_fill(arr, 100000); return 0; } ]])],[ax_cv_[]_AC_LANG_ABBREV[]_openmp=$ax_openmp_flag; break],[]) done []_AC_LANG_PREFIX[]FLAGS=$save[]_AC_LANG_PREFIX[]FLAGS ]) if test "x$ax_cv_[]_AC_LANG_ABBREV[]_openmp" = "xunknown"; then m4_default([$2],:) else if test "x$ax_cv_[]_AC_LANG_ABBREV[]_openmp" != "xnone"; then OPENMP_[]_AC_LANG_PREFIX[]FLAGS=$ax_cv_[]_AC_LANG_ABBREV[]_openmp fi m4_default([$1], [AC_DEFINE(HAVE_OPENMP,1,[Define if OpenMP is enabled])]) fi ])dnl AX_OPENMP msolve-0.6.5/msolve.pc.in000066400000000000000000000004431456710632100152730ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: msolve URL: https://msolve.lip6.fr/ Description: C library for solving multivariate polynomial systems Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lmsolve -lflint -lmpfr -lgmp Cflags: -I${includedir} msolve-0.6.5/output_files/000077500000000000000000000000001456710632100155565ustar00rootroot00000000000000msolve-0.6.5/output_files/F4SAT-31.res000066400000000000000000000004711456710632100173350ustar00rootroot00000000000000#Reduced Groebner basis data #--- #field characteristic: 1073741827 #variable order: w, x, y, z #monomial order: graded reverse lexicographical #length of basis: 6 elements sorted by increasing leading monomials #--- [1*w^1*y^3+1073741826*x^1*z^3, 1*x^4, 1*w^1*x^3, 1*w^2*x^2, 1*w^3*x^1, 1*w^4]: msolve-0.6.5/output_files/F4SAT-byone-31.res000066400000000000000000000005051456710632100204450ustar00rootroot00000000000000#Reduced Groebner basis data #--- #field characteristic: 1073741827 #variable order: w, x, y, z #monomial order: graded reverse lexicographical #length of basis: 6 elements sorted by increasing leading monomials #--- [1*w^1*y^3+1073741826*x^1*z^3, 1*x^4, 1*w^4, 1*w^3*x^1*z^3, 1*w^2*x^2*z^6, 1*w^1*x^3*z^9]: msolve-0.6.5/output_files/bug-2nd-prime-bad.res000066400000000000000000000416421456710632100213740ustar00rootroot00000000000000#Reduced Groebner basis data #--- #field characteristic: 0 #variable order: z1, z2, z3, z4, z5, z6, z7, z8 #monomial order: graded reverse lexicographical #length of basis: 27 elements sorted by increasing leading monomials #--- [z5-1, 64*z4*z8-1, z4*z7+64*z7*z8+64*z8, 29580*z6^2+437724872*z1*z7+218862436*z2*z7-218862436*z3*z7+651321344*z1*z8+325660672*z2*z8-325660672*z3*z8+602309423872*z7*z8+1272112*z4-59160*z6+404840790991*z7+1204781711104*z8-93554153, 7395*z4^2-437724872*z1*z7-218862436*z2*z7+218862436*z3*z7-651321344*z1*z8-325660672*z2*z8+325660672*z3*z8-602309423872*z7*z8+59160*z1+29580*z2-29580*z3-2544052*z4-404840790991*z7-1204781711104*z8+328271453, 839878011719573384292822863263461468487680*z3*z4-247452930568404324596018427299446537120906181617288*z1*z7-123994032258501573158451414262651988106169991269604*z2*z7+124528017870526228657251086881942739472975700355204*z3*z7-676466270244454039972722812226029379199934039057187650625*z7^2-368798680834803642988071800125796924849294099746816*z1*z8-184399705698140709848769536761140255885283508799488*z2*z8+185989147551255316360719745419726914754551451650048*z3*z8-7549448515154210116903041543261229014257925938045155858688*z7*z8-4153389196568356420043592768781221726804812440072874299392000*z8^2+33498330998348073264125514814099753262962462440*z1+16749162558730581323794265345500812431279768340*z2-17001937537018472527469446240517247020981963700*z3+720228604147563343994834637326607196294269743092*z4-1010808541753751732741392381528618033646092820096420124284*z7+2724764909269400538060088937976901067184475709616880384*z8-278562272461788310109991430500132367854778061333063, 9331977907995259825475809591816238538752*z2*z4-6029285586739131345257615894801065157682861745384*z1*z7-3000978304386163940133749827777674379612443927444*z2*z7+3017008985533990882290984602041393585883207419572*z3*z7-27708935407096284829223809436158427738768104576933400050125*z7^2-8971396378777782334116188570767431567133146664960*z1*z8-4460951944508775667922863863649412113884539201536*z2*z8+4489227595931225436433087520525165001063776380928*z3*z8-378944707012124664932321839011014070191881601187161228544*z7*z8+113004862283882829680587919329723649034961782774785652436992000*z8^2+814396798840718632026153793237792615761423304*z1+404068202215470426118131001600460025533507844*z2-407519194607353727420557013475864182906477860*z3+22289913276381428353955767350788357169947900004*z4+27589208830374216603900390461041625393995088504942261098228*z7+97954732686799293822110853249373842519558310987759360*z8-9172147366707565547662636814692217279694885186267, 1679756023439146768585645726526922936975360*z1*z4+297855293527941657155797013470190889608948374735496*z1*z7+147430854069953805688536519892798876045242103805668*z2*z7-148338473761169831710509051027964900731770615036548*z3*z7+2493129182405583781692941337894655896810456852818561717810625*z7^2+443398726783931387478329898784434333985304227745792*z1*z8+219472695967185657087683284907693412389349839128576*z2*z8-220426342765307381490534227289710268142260281706496*z3*z8+26577302551053407567320204426860820263969471030897589278976*z7*z8-10174582018083588795006310850754911251725180665878956210450432000*z8^2-40447616447312249122638035523778683757731235560*z1-19942093409304440143426336135841340310995224340*z2+19999829630796899574355172506094984378793527220*z3-1288962867530096361932284834940645508936626840564*z4-2484037422562904604880960525059931595627190783151822324277252*z7-6101439920864683537482354007487948265093051844447632128*z8+548064295062064654520689708522346262747450761807431, 7395*z3^2-437724872*z1*z7-218862436*z2*z7+218862436*z3*z7-651321344*z1*z8-325660672*z2*z8+325660672*z3*z8-602309423872*z7*z8+59160*z1+29580*z2-29580*z3-1272112*z4-404840790991*z7-1204781711104*z8+273578033, 651068226139204173870405320359272456192*z2*z3-19826715298209733398205198448829715735244314402408*z1*z7-9831365912735328304417483561886882468197581914708*z2*z7+9891909533805370418963786399256898489773716574068*z3*z7-166253600300913411696425185730394538647913386822580702912125*z7^2-29461805696946850207711978202045478450058905899008*z1*z8-14635446543283323073420443165437902895554709399552*z2*z8+14699068864972387809556648026025141895142017361920*z3*z8-1772299827034989282123766517880238833853660376415545144576*z7*z8+678489066604628701286327600868198407625034574177008161730560000*z8^2+2673146473623883433439668664905238980391268680*z1+1329830305136699287618354170441476206013830596*z2-1333680428058115192225738749523785737561943012*z3+85954123985530975218762414192282060813095634724*z4+165647318902191038665166337222500202973181159148769567154932*z7+406872787484243000113848097204919802949209766448353024*z8-36547512125199028035797894161441663488156909107051, z1*z3+z2, 7395*z2^2-437724872*z1*z7-218862436*z2*z7+218862436*z3*z7-651321344*z1*z8-325660672*z2*z8+325660672*z3*z8-602309423872*z7*z8+59160*z1+29580*z2-29580*z3-2544052*z4-404840790991*z7-1204781711104*z8+328264058, 19532046784176125216112159610778173685760*z1*z2-842321873899346835089067730092773500196003961843592*z1*z7-418968824177635223105524656720190848734261035300196*z2*z7+421051363292934452930371200073046684763328417760516*z3*z7-4988284658200571761166021224676071418079847027254065649590625*z7^2-1252753427900718525522821815295462074571894720303104*z1*z8-623513390057891555788518218934890726997132389107712*z2*z8+626215646433053969717657065981892080705510623905792*z3*z8-60720484546604251659066280552991669257279619779257333446912*z7*z8+20350517485949076391500990599437071665684142585332041489772544000*z8^2+113701938740926662679994386868292094374528359400*z1+56648678478967566166743891927254644224271707540*z2-56836358950984531386316766711080133099324492340*z3+3299050419744076247896298639519113862520901801588*z4+4968408485222671973198266701048439356713833751812738551363844*z7+14931688438835208958201373597876929403267099663049054976*z8-1375063676384482149619025207295230650095288636094247, 29580*z1^2+437724872*z1*z7+218862436*z2*z7-218862436*z3*z7+651321344*z1*z8+325660672*z2*z8-325660672*z3*z8+602309423872*z7*z8+1272112*z4+404840790991*z7+1204781711104*z8-273548453, 103885415506251221779744690798050145080983131269720106450496345289523200*z8^3-269241306102813772282794911951970164573127918428253271112*z1*z7-134474965716350595756427347754043577429030485147779404484*z2*z7+134693359151728793177445372496975465873990085162123605348*z3*z7+3416794797971609913238654438720923196455602499074647325724496026375*z7^2-400622677541325322210680357989643978142867837620630818816*z1*z8-200094808937945418646270150029025602757240149250999552000*z2*z8+200419640390232790807572653938818095056867823677270214656*z3*z8+25327047069983981677539794685704743210698272942871655771953124699904*z7*z8-14076267811891134024186321819905499224163306215607474804379131372011520*z8^2+36374100787924271522356809949505821670919851762989992*z1+18177218622262128244316014371755274412256974943826036*z2-18196887514566856489687245741480236180815901811367956*z3+1173317367763806951100145530499491018728623254860184148*z4-3436579430774988460385329906571103855243642197741845166902334406748*z7+6015887768093218139804538641044400954750736953354234670719744*z8-512856136342219070930215935163055433210218981804093030671, 4096*z7*z8^2+4096*z8^2+z7, 40001631813992704442597702882873699708436480*z3*z8^2+2442299321818732776173531780442145066744*z1*z7+1223791909233710262264983918425951013852*z2*z7+8550155840617141123460571372146031221188*z3*z7+6680166241400348302892054902321412977805739375*z7^2+3639964651432682849823207835495517974528*z1*z8+1819981686434494350504069163340999604224*z2*z8-1816051480662532964825658609823415465984*z3*z8+74511304967619623367048081311729841280804607744*z7*z8+40978016430574291517077699926694840495183522529280*z8^2-330620641296165365308555167729676440*z1-165310291610934832254226041604356780*z2+165131814361532127808925960113440780*z3-7108537137362759598210315650002208716*z4+9972790608876779738823269495883714484559017412*z7-26892910058283795982606773800075627575612672*z8+2749360406834851664667075139043845865609, 1333387727133090148086590096095789990281216*z2*z8^2+179235262785800652797566051139567258936*z1*z7+415186704098101049526420537436698865660*z2*z7-89687824965733256930764119739911972700*z3*z7+823107922405196265381702932192974753512342936375*z7^2+266696596617345067911371253875461812224*z1*z8+133269528120332660203874103209266640896*z2*z8-133452999142298399130925898615831148544*z3*z8+11260774438797168451906302238862764765686406912*z7*z8-3356862816857658120482909514085868072676952442044416*z8^2-24209963699512458514972020388049880*z1-12101403988730617259311431536300364*z2+12114498337540459169661021439583148*z3-662516169242458574645081813396470124*z4-819550482971317607471966170833604328282553973916*z7-2911248450567820303183579666646092475493632*z8+272611707455894580301209851504625689281, 80003263627985408885195405765747399416872960*z1*z8^2+16605212330770509795564342869370133402216*z1*z7-1461823767446422921868735893117511904172*z2*z7+1470805143326240529724598652785887350412*z3*z7-24686557505914487613148195910886921192392482351875*z7^2-4357002083686290908624802186023018835968*z1*z8-2176138575474796316165590135564340844544*z2*z8+2185572911905729869655554551278860212224*z3*z8-263285041196347314694014820571503695441389112064*z7*z8+100746936525184582341968640974283708209360612429168640*z8^2+395678269689208390140605443911819960*z1+197731828050983685525116904484654140*z2-198303135764681647280904683074053660*z3+12774625993429314592105278585378843356*z4+24596505351778984228693941888047465866452448257548*z7+60459085323567936538811156813219419494363392*z8-5431301955590845183335584583996783981589, 839878011719573384292822863263461468487680*z7^2*z8-8959796879422440491689180287128*z1*z7-4475046137613661979480872935724*z2*z7+4482319180719856319024121475084*z3*z7+112305589308319997200131011166512270256285*z7^2-13331898672029752257991150678016*z1*z8-6658737543463354304860623689728*z2*z8+6669555226957946261927769315328*z3*z8-1183024279221949120354227408925765397248*z7*z8-462694786140893367198225077365191646851072000*z8^2+1210455006329072998674565560*z1+604899932645299497877664700*z2-605555029052659677976721820*z3+39034534097648582768621042012*z4-112962282065513879071234165265862619056244*z7+200076653309114376681299881824145664*z8-17059907831005009592155886848693, 53752192750052696594740663248861533983211520*z3*z7*z8-4520086079693559230282176385524171289540648*z1*z7-2264930538059625251005223898385722537042484*z2*z7+2235625734543773836768410360542132636807764*z3*z7-12356635924620544043369275045889963889240480163125*z7^2-6736657622337345890430379908259119768621056*z1*z8-3368327628657227562162403605189290649806848*z2*z8+3353790975647184871839735601350166038980608*z3*z8-137901930505179986952530287585859175909438864141568*z7*z8-75867667632121929052414545287213896083471026245632000*z8^2+611895520052222921029807442121704799240*z1+305947706314654093915485736461457903140*z2-305287501031130745248110791259501293380*z3+13156110369159865622421458324592748667012*z4-18463881395027313945279242086036280654443651111084*z7+49772037833443004884570829022606400088185190144*z8-5088374919611728004140795714722765162457843, 1791739758335089886491355441628717799440384*z2*z7*z8-331279704502269492193134878027046971247928*z1*z7-166192972187417399727113117671230106991612*z2*z7+165769622621283276249602199831638959826780*z3*z7-1521720799380636164310892434999801173113591559160375*z7^2-492934147494370267532053700830335384383488*z1*z8-246563803609110153157697085113126745012224*z2*z8+246660639416891491492921962332438569564160*z3*z8-20815874221238780460695604817058800543671485177600*z7*z8+6206002523934295226982192270350069002117516357373952000*z8^2+44747163020911981006536915236429965272*z1+22377975127004183607904641970411523916*z2-22391175117568892931470111652726234540*z3+1224590146287005661961756481003155493740*z4+1515144538145914401042917717689067554865933866805020*z7+5381274544110098224036701349886477364185656576*z8-503899315266520014140653561058250996969281, 107504385500105393189481326497723067966423040*z1*z7*z8+5379235679305352683017382995860242480059496*z1*z7+2701323939528310314560926152037682988787028*z2*z7-2717928256060138024472412154693538474076788*z3*z7+45639267345494464385283403774948145229518506294648125*z7^2+8036829360235465260184445271282757439967232*z1*z8+4021317758486928594895116025520419539101696*z2*z8-4038759485730411435274530345938898886486016*z3*z8+486673670491061365662018946053693250477564992025856*z7*z8-186255943385660978738518182655789283959608961747464192000*z8^2-730519370575136509166300014971194158920*z1-365391547495471414321653522650887814340*z2+366447752495936042695992558322285742820*z3-23609987461361040321092927209736651150884*z4-45472800098021503041150708248188072647003643629121012*z7-111746850402328690613844760995859936437884063488*z8+10038371882401165633202432856881513588580011, 1019216457772633533410034305510398608108760872849087734622912123863821457922804300000*z7^3+267803583331588366418977055996836377989590005535756447877112782533199528*z1*z7+133721219136127422925707126486768021244699145577920544238487465425818484*z2*z7-133984452101165886926847409900168455167002734512137534871786846225147284*z3*z7-1016179568600761831665689530944929495104973598729324162209352733254010471713108502875*z7^2+398483221914552109594233960728381325827827950831910684278247582425829376*z1*z8+198973323628130148764623403043363826494120818799656186848197065004279808*z2*z8-199364752344393113569708263425142905132053541576226001548654010974251008*z3*z8+22550473982280699730572372880552373024399019452677226540083664297318894021901568*z7*z8+4162304689491135681389504914227949740513935613435482702493168553535523903362951761920000*z8^2-36177747609488133794216288641187811523461204325951538938548400769160*z1-18075691189082266499328371603635687434091162141399006976253323241060*z2+18100058836371772920561274240132088975890192270953773983938212790660*z3-1079464466769812041193747842233341590301383584525944581510930187147972*z4+1016187661161671122998261391849925629008308042221262241127616103494295254273261116684*z7-5062914721349142781187536915683253761395045168915979225717905795170946918144*z8+456211058253720257417409063552344198583357700116007934909498108633534083, 66794239675793015903739589088058171070258314240*z3*z7^2+16692710370444121695110351604497067685745261048*z1*z7+8364414508810215374409576925754969948362095964*z2*z7-8310234571259822264380406570257127904787325884*z3*z7+45608193040432464762299427191984486671965400620415695*z7^2+24878554025220156168025363495337188977658228736*z1*z8+12439272644015331594059384339886011361004730368*z2*z8-12412395831315806497054964839736293990552434688*z3*z8+509272050365929971820138838411598155002606585288177408*z7*z8+280280664969607498671115871098955321004092906942361600000*z8^2-2259737187921426632051138152109648529680280*z1-1129868395532536240718824099320513621316140*z2+1128647709281494208182359162113350362054540*z3-48585662531005188085908336857783744349688652*z4+68211861836686261133955000623912567204816248402317124*z7-183808518674095655518349747664599377057370476623104*z8+18791417615281683205632808834610813130314746153, 912684255760398080246796555026458336266396523304390400*z2*z7^2+502173451744878247101895165762490090809935874200863096*z1*z7+251184924796464147105728651770521324184829226254396188*z2*z7-251283391159128209440933972388312615352201055893713788*z3*z7+2306148460941404981072303823778174121800225286406243133275765375*z7^2+747218758416354763562187130567259954478461539957010432*z1*z8+373388883157394778265721329894398467189315245123680256*z2*z8-373902725431058969905713400212533931224359911424915456*z3*z8+31549948051087455849481948576927655506827264404284715658462976*z7*z8-9405114217669556100863130188960671141658707174776968052679249920000*z8^2-67830408207644452183745617865537888147432831056920*z1-33905191096144288302404967600350880610973390791020*z2+33941866983666559179354534917588100132598334351820*z3-1856208746528889245574032645278560796648195141995404*z4-2296181381250911868087907035334517983481730198098895854412155612*z7-8156608611753821128114071212657750942313821155473433879808*z8+763791541294702117746436234836303975675641492003225881, 2433824682027728213991457480070555563377057395478374400*z1*z7^2-364455878389008349166123162142486536574103210619658328*z1*z7-182029851516679137406921505709503410164172975295132684*z2*z7+183148234591372323235635247874197282470718637704943084*z3*z7-3074031883878463634324476891542015768245149281080961677098534875*z7^2-542543968597913118058474561188675947849697885218123776*z1*z8-270978069183984789359701598950684887071649599825451008*z2*z8+272152856029943493633255477910172067762446283697707008*z3*z8-32784905717445930908593671220544840531689001499827165556531968*z7*z8+12545260518634221236860589131850544784625890855666018478100664320000*z8^2+49270790609996691584354676878190701317651811274360*z1+24622048244528160344641999254379726247141408613660*z2-24693188890397733175024454883561651433067920766460*z3+1590727797071799677214365209028043436610854384246972*z4+3062818365783766491723272903015800852374915434541500685254411116*z7+7528514314359410306251043980915430896666503843202111961344*z8-676319078471125588102623072329206227477734695087195133 ]: msolve-0.6.5/output_files/bug-chgvar.p256.res000066400000000000000000000157451456710632100210250ustar00rootroot00000000000000[0, [1, [[[2606494943347515047138634809021796624166384390841758692672282559828202832506225 / 2^255, 5212989886695030094277269618043593248332768781683517385344565119656405665012451 / 2^256], [19613276288264956083908691349424102592877149849370739618118444337517838188983 / 2^256, 2451659536033119510488586418678012824109643731171342452264805542189729773623 / 2^253], [34920674592991439017236863052172999544704796936776352401783769005730613839267441 / 2^254, 139682698371965756068947452208691998178819187747105409607135076022922455357069765 / 2^256], [540885538069380287087984134095240059718584175084373749355321366122278204017073653 / 2^255, 1081771076138760574175968268190480119437168350168747498710642732244556408034147307 / 2^256]], [[837908226308445135027231978356435432693356675435500258612522358364242803997861 / 2^256, 418954113154222567513615989178217716346678337717750129306261179182121401998931 / 2^255], [10530058875165095765087847695374322303480778358459663743777715109768996961097 / 2^255, 21060117750330191530175695390748644606961556716919327487555430219537993922195 / 2^256], [1800532195615165747687899534877132599905875437442226305503806099065397709884877 / 2^255, 3601064391230331495375799069754265199811750874884452611007612198130795419769755 / 2^256], [5768605811964381599606065587767129442106781390729871025722291408611082536414649 / 2^255, 11537211623928763199212131175534258884213562781459742051444582817222165072829299 / 2^256]], [[5081213661087957008899163023563018985577302626965683450466068119344905472392583 / 2^255, 10162427322175914017798326047126037971154605253931366900932136238689810944785167 / 2^256], [-1165860587047760961471161023725318656297950420615745115690818207740145808227 / 2^252, -18653769392764175383538576379605098500767206729851921851053091323842332931631 / 2^256], [159383682635610700541051059816417782516155228456080888366570071543966450235295 / 2^255, 318767365271221401082102119632835565032310456912161776733140143087932900470591 / 2^256], [-60938501059019781199085718659537673651589965757589537718195682802602874312551 / 2^256, -30469250529509890599542859329768836825794982878794768859097841401301437156275 / 2^255]], [[5007817477014756005890439507724996988549065858670760981791555864572001257644051 / 2^255, 10015634954029512011780879015449993977098131717341521963583111729144002515288103 / 2^256], [20004048192923314314970509531509242921442935460876225159417181307156412342589 / 2^256, 10002024096461657157485254765754621460721467730438112579708590653578206171295 / 2^255], [159384682754314289418815771980494520593544376444723798995058953371990469086627 / 2^255, 318769365508628578837631543960989041187088752889447597990117906743980938173255 / 2^256], [-61738844171110278067341561993554845836261812138506448796090638000681387148795 / 2^256, -30869422085555139033670780996777422918130906069253224398045319000340693574397 / 2^255]], [[60730340251718830645575917321553278676725504270167182532381364145038184447431 / 2^255, 121460680503437661291151834643106557353451008540334365064762728290076368894883 / 2^256], [24233278549846987212257574083001832289818217367341155934253317134650892473977 / 2^254, 96933114199387948849030296332007329159272869469364623737013268538603569895969 / 2^256], [46159894870723157970658676583986869744828244920865580822261545692266126940465 / 2^256, 721248357355049343291541821624794839762941326888524700347836651441658233445 / 2^250], [124499333986523987465939575996544583062981487804364928906833663400632511898793 / 2^256, 124499333986523987465939575996544583062981487804364928906833663400632511898859 / 2^256]], [[43837849087234767052728204657023666425046382158644712606971523051571650872231 / 2^256, 5479731135904345881591025582127958303130797769830589075871440381446456359029 / 2^253], [193371626397437755439175008765956219525704826797616427666483412962251096464321 / 2^256, 96685813198718877719587504382978109762852413398808213833241706481125548232161 / 2^255], [43057165693541190144944336349291738236752315989797494710923032556340044969501 / 2^255, 86114331387082380289888672698583476473504631979594989421846065112680089939003 / 2^256], [-25451631003100985812725914954883082887285250447642029234242246342496769563529 / 2^256, -3181453875387623226590739369360385360910656305955253654280280792812096195441 / 2^253]], [[82465431493205080407635248436227785379710919801237608929252609370140908935945 / 2^256, 82465431493205080407635248436227785379710919801237608929252609370140908935957 / 2^256], [119342829475861280869275914443475296377668039041757427202202948761188491569413 / 2^256, 119342829475861280869275914443475296377668039041757427202202948761188491569439 / 2^256], [20026571617679676739282705509838504842599438017839570024125137506715234235561 / 2^255, 40053143235359353478565411019677009685198876035679140048250275013430468471133 / 2^256], [-82330472910267711205241267554782726983066608713797900903798096765261063165989 / 2^256, -10291309113783463900655158444347840872883326089224737612974762095657632895747 / 2^253]], [[92212433600921786678488544565840429288234736369793859356607519909330806566343 / 2^256, 11526554200115223334811068070730053661029342046224232419575939988666350820793 / 2^253], [-21102343241357834087039637853599736401774478871007714415812330178689036639109 / 2^253, -168818745930862672696317102828797891214195830968061715326498641429512293112871 / 2^256], [61080342051906404006553783588557331961832980794514653560756073584838224518373 / 2^255, 122160684103812808013107567177114663923665961589029307121512147169676449036747 / 2^256], [63463180460338307093879604775305878870361400688008081575481278176541616009645 / 2^256, 31731590230169153546939802387652939435180700344004040787740639088270808004823 / 2^255]], [[151923570680849581417123093323648851839134618154471048158504414897770003137 / 2^249, 19446217047148746421391755945427053035409231123772294164288565106914560401537 / 2^256], [-297608725393628381023755894633938691955674716176351098541685526870866823784333 / 2^256, -74402181348407095255938973658484672988918679044087774635421381717716705946083 / 2^254], [102774704970030175156208087945820579818905558748500936391709348663571912589411 / 2^256, 25693676242507543789052021986455144954726389687125234097927337165892978147353 / 2^254], [11732857903706422323787104200655838801161697071233266977667657345679676405181 / 2^255, 23465715807412844647574208401311677602323394142466533955335314691359352810363 / 2^256]], [[26231402220168492386911311598601399294410445648821232414704636581092750994409 / 2^252, 419702435522695878190580985577622388710567130381139718635274185297484015910545 / 2^256], [1564843412194300122876779311439880265685356580691193184773212738789523467325 / 2^253, 12518747297554400983014234491519042125482852645529545478185701910316187738601 / 2^256], [928739245647604584091051520110282442878929134853892326251466481827114336836793 / 2^256, 464369622823802292045525760055141221439464567426946163125733240913557168418397 / 2^255], [-533446845656366184912639909734360754902303533404260873809006094577845424533945 / 2^254, -2133787382625464739650559638937443019609214133617043495236024378311381698135779 / 2^256]]] ]]: msolve-0.6.5/output_files/bug-chgvar.res000066400000000000000000000077271456710632100203330ustar00rootroot00000000000000[0, [1, [[[15319600406759311279748950765904158043931 / 2^128, 3829900101689827819937237691476039510983 / 2^126], [14409559673732612038632808778700401347 / 2^126, 57638238694930448154531235114801605389 / 2^128], [410490557109648206507895885740587264340339 / 2^128, 102622639277412051626973971435146816085085 / 2^126], [3179039472210149283343515975030212067269047 / 2^128, 397379934026268660417939496878776508408631 / 2^125]], [[1231195483166375101033967204361512516913 / 2^127, 2462390966332750202067934408723025033827 / 2^128], [61890123607913306301466379005685955835 / 2^128, 15472530901978326575366594751421488959 / 2^126], [5291288561048193107176309412527934968339 / 2^127, 10582577122096386214352618825055869936679 / 2^128], [33904817720423727345775268306844647680281 / 2^128, 16952408860211863672887634153422323840141 / 2^127]], [[7466172442412408544795727821783540203721 / 2^126, 29864689769649634179182911287134160814885 / 2^128], [-54818501356839951484895562809996582675 / 2^128, -27409250678419975742447781404998291337 / 2^127], [936773092757063492454318865261432226131 / 2^128, 234193273189265873113579716315358056533 / 2^126], [-44770539839034835945583172309554218245 / 2^126, -179082159356139343782332689238216872979 / 2^128]], [[29433305770899831525447638201843798761827 / 2^128, 7358326442724957881361909550460949690457 / 2^126], [7348326763861920280739804349370071173 / 2^125, 58786614110895362245918434794960569385 / 2^128], [468389485463247297316288699630786806479 / 2^127, 936778970926494594632577399261573612959 / 2^128], [-181434156373594113533553379330236815789 / 2^128, -45358539093398528383388344832559203947 / 2^126]], [[356940859447054316780803362719188489363 / 2^128, 89235214861763579195200840679797122341 / 2^126], [142430410186240245305984728867120695099 / 2^127, 284860820372480490611969457734241390199 / 2^128], [33912934784428598456257843545888262523 / 2^126, 135651739137714393825031374183553050093 / 2^128], [22866916215983776639567034994840870223 / 2^124, 365870659455740426233072559917453923569 / 2^128]], [[32206964971402775921687490567204882675 / 2^126, 128827859885611103686749962268819530701 / 2^128], [284134068049382510972053292908280701939 / 2^127, 568268136098765021944106585816561403879 / 2^128], [126533637587942174964991773214392191429 / 2^127, 253067275175884349929983546428784382859 / 2^128], [-37397810579198249416961518632295913211 / 2^127, -74795621158396498833923037264591826421 / 2^128]], [[242344122145962323916462752377567108931 / 2^128, 60586030536490580979115688094391777233 / 2^126], [87679263662514071805775484194976937619 / 2^126, 350717054650056287223101936779907750477 / 2^128], [29426402253650524731890616914230017175 / 2^126, 117705609014602098927562467656920068701 / 2^128], [-120973757258183838635580510727502330413 / 2^127, -241947514516367677271161021455004660825 / 2^128]], [[270987986933647118154757782905255024781 / 2^128, 135493993466823559077378891452627512391 / 2^127], [-496113705386580270675790922564246201423 / 2^128, -248056852693290135337895461282123100711 / 2^127], [179498992570772467225653690447674792067 / 2^127, 358997985141544934451307380895349584135 / 2^128], [11656345330678603060300343061045370363 / 2^124, 186501525290857648964805488976725925809 / 2^128]], [[57147295709468540957619583419442219169 / 2^128, 28573647854734270478809791709721109585 / 2^127], [-874593438639079062616877477807025914033 / 2^128, -54662089914942441413554842362939119627 / 2^124], [75506928187311091411038255659557397835 / 2^126, 302027712749244365644153022638229591341 / 2^128], [34479770462018814968289149501513663753 / 2^127, 68959540924037629936578299003027327507 / 2^128]], [[616697302479105464219603864265542945103 / 2^127, 1233394604958210928439207728531085890207 / 2^128], [36789291819117441728410105257375194043 / 2^128, 9197322954779360432102526314343798511 / 2^126], [2729319341614279898723659905584030185729 / 2^128, 1364659670807139949361829952792015092865 / 2^127], [-6270637535330271692444200364014446781829 / 2^128, -1567659383832567923111050091003611695457 / 2^126]]] ]]: msolve-0.6.5/output_files/bug-empty-tracer.res000066400000000000000000015117451456710632100214760ustar00rootroot00000000000000#Reduced Groebner basis data #--- #field characteristic: 0 #variable order: z1, z2, z3, z4, z5, z6, z7, z8, z9, z10 #monomial order: graded reverse lexicographical #length of basis: 102 elements sorted by increasing leading monomials #--- [z8-15, z7-15, 2*z3*z4-1*z4^2-1*z5^2+z6^2+225, z3^2-1*z5^2+225, z1^2-1*z2^2-2*z1*z4+z4^2, 7781720731374955954550675507673901881244151200024337940433044635745733930993382951937403403742858301407672433534805689274460991508384753676019680728406909367265642541493155376956000*z2*z10^2+1752778293916862001220804306992280387548245141084215810963773769277886644225767915319674864414829052300440689836132401440434046390767445799892893906021325543690291738060859336430400*z5*z10^2-734977352401369896439809521264379642399234623217131627050941194916653762079353696458989284324605073282299025924885693844905909193851463019149110543480533137172460681872180225198350*z6*z10^2+49794152787831670561012816719880193375956339272200968516781063429777293073379606584688868452316491387825575638493054628872048123734303099705342233592275499225371938596614538988385000*z9*z10^2-2653024484813100501437769815085714949475120152668751585460281045484694354663687752468206912481941140818434565529399402077076240724104951739443090656825795066172770904893294927696765625*z10^3+1107442332414887191471968297314970810659861753898915339540418673944606104099918439197368810929377012106109142080697902774168011285283415162110270618061131655640901853852175056*z2^2-124443869531402231453843129010207765678109701717696895583804661510310900307838125783637368825540711780537423930718213925169572867378360725471149375428770816730195694584806650*z4^2-2705482608344290270473950397476550197950273442503683606606968800768295133701114281925617017548297685783064207280310043501743971752206981382492757661440063033626840672237378696*z2*z5-119009737672282211763005704214597813363682263706656899457088804579689989207232774478670880284261356390621353989068642727990513736600772495008401293034711924162906989514236130*z5^2+2887681867530931668827661595980599326122559029421729721884992170786519135207379981798566400820586526863734373122626832680656484926199757245076907260470270885129697354074702848*z2*z6+1220364162616112316205888330337005310537697152532795931765876090824358274305262958694696635398434309546739849948610952503373633822340548620032917892410334517936100165173883488*z5*z6+37121643847623658129809135930229060290069506168165034753082583085082839511237325264178762248352002330379119724928850856049353227317974071471328073022083191702506461605460602*z6^2+4365077475401777890832134678446338788179643337804880585403934706200479481096143787082440739224879309345556034212536114173924295048845402385081549687987036829853948044319726336*z2*z9+4765389061581721431839091084418139617859946514421280912841847947706423098042512324240976563219385159685079544032901989963010712736286506123275238190307608223353672063052583296*z5*z9+9514311739515472099585265365971516131446946856001568111869779655736114721556197216215732623784732680634306630584789969860112244195756731457575735944095917717562949495885291904*z6*z9+151175351543189088906696000767771280533911097765057253662711952886056467912790847443734306768643746785616781547504842750049373103928614685755280810806140929764315217920000*z9^2+81998555704078729198261441893460850984308977477606562663593117574619123965732598664332477381053842884250727385214245983571435514970052253857956898047057051639229261013091833786784*z2*z10+16217347471532189924500121735101795098113826661622150785807759551471861295894936361917524257309641067420883251641547604654407732889317033800750486720781558280872709544493053026908*z5*z10-11125813588203989327942517638631488828800258970458824204126020573233398635541297568437016439326711387367824608268028201224922036341773466073181342716203352676547390284251721288808*z6*z10+449256496819672720493384030199820944516316663281155661804370972335624120931305356424689898241448104236531944470069861060837782305604426440056243532595054190958751734830154084341200*z9*z10-34544367360934417083209725583068513100850110156848118826501222281314609048554324830382918666855968638340220040337201555426929264570920468253599376037851932709562581176924925672356000*z10^2+214109652107904792604693034081083165986149499263885483774312085253316831145211765898532076746818939042600480665812372699274464064294817564958278415264907541030508882660992739040*z2+38165571135353559694827522139711388861142903628071369542690453377281682121344499974503046011782056625688778794626558954813786817406729990519835914265550437936850482641088214788*z5-36343101952936393724191564105475330643848830799555748853717640995260118538656832768475013740537274016158696085490311094378315837928933021831497900003368677404430924754661831130*z6+1019567242556465579819985961777671185039503352921510497178215804030276335501327181030944956972250807864841489771503034561003521418569121158054746909631008948572138566150291943528*z9-157054103475133169897957104320015027629876698317875318428406697008802481383446845221644187317682546566919211751682613072709666731906169549138430317608937303261046051073513292711545*z10-274990981393198946095950388971989814708097270642502711935459731706876156407229124422175988515429723863540568865892151046520057554648958234783458226916687477574929919679650358188, 112056778531799365745529727310504187089915777280350466342235842754738568606304714507898609013897159540270483042901201925552238277720740452934683402489059494888625252597501437428166400000*z9^2*z10-3224261997623715961720372029758781114539381541065145375255949680968421805288003960384432784893530984205536445691743715918613401514294579126907741672398911113846747712976054213650413346094300*z5*z10^2-6153029141840869683086667895374275617237356439009527666150203708600143495514177836820099156977756009524675085451674160479886639640016034071022346355936195305818111666554936037532660667915800*z6*z10^2+163826219626383425657238352633411131596691870710060736880669453034984613892475196244841735493803724399753618449082268716270643656930330309272751348219050395913310296172442457387447497638405000*z9*z10^2-6716164256145090049643925162162107576091170245195089756705802547577169040501935831840705641208039356796063823019849196984762112187575162981137315909063581535785161716531171139069486591980078125*z10^3-1822472216347807184500945840379187572443821394403437018952529592970818882324851044454512423834577230759106322892556183583205746304629260310669418879623118036807303729269109947490428992*z2^2+6500856105581972812311320364793227961386670520182199283006899883539337243172097654446268399325488595217669514437978365899766158632785913496382118360090228636484279451865741560055231470*z4^2+9766391630132837822786689642095959422562796016303646027930743537756157823778749124981140144501381397840570476771713135757427516274019273273058052579004965134386831142375080218452332912*z2*z5+6717270166431131597223412869461115952552639897936773716049056339240090745798295325730101040678937745850774438607282734315964997831080989984432151195051721851211629211259244073756489190*z5^2-13073075171325955590782888808641347050929435213936969795729313111802273607434809278685312045534082781711825749235259211011008636673385486938079177646841295506172474143218652782247684096*z2*z6-5168306420898963421375340076439110317137687575841525885506406932316796631180827108197337731746573061556108371412586432893428564239120355931927636961750521148805778514876830568257894016*z5*z6-7496175947232480224575333418255438110752540391894737492587297662035146642849756979448817428141706492741768564413486257798646912789151927755048425733886729746208787889963157135476726254*z6^2-193117180249982308971542948677728737397825932927786795801565883079363550267074713789142984969965291684547581880934903028863762588248803623539380712859771006947672835363576791721997948032*z2*z9-50492841901332485937128526015812389367778795823733684067923029957792672930211787974332340935012893201129267861715260394986425259162102081643740639585004832098839067907616804230741401952*z5*z9+38105027340736899183967701759039676523442192714454437692345264729467775640770439466428110246813979704865768474543063323751060262088313940672445899425628594469871959259463717120054711072*z6*z9+498143059638674754699167536503105605003116837503207471247650723916825968549427359562877334622392232167174097370182451179665817808491524985647833610437806485585391535914041002684160000*z9^2+139866180714423488000194960964553744488737496225264264928699218432935624539553851486192801589150573490357092502494004628555949835153728986525654957805811785114118074947405440612330586002592*z2*z10-15648713845133495423106761723587442276908820174997741971968800313957887266794808742372710984501610647369548673730655073797760931865988976527035259071830338092116866234291268852691835753656*z5*z10-97193026198053505183431639449540515371491238812296053541255083343952372796575300743768099830577303793023167154631316947538653868552109944634952866405680908028349077323822618279400450956384*z6*z10+1278633448105390054508932687094225404608162461740880653248962948851089672765247209838487316540602162514175214650559164277382547258203197551685788010920408858903959943199057908672903185603600*z9*z10+53672895211132767400231740135978959145165395370716735303129306891959790017342322997557099895754119447153520930321488622038712097989812848457960697815220460978186913945101414401180775920477875*z10^2+607726217461017107807980599709000984356224372851168900143584582357431526922460871245435936756072387447383823930140629604354990898304160298503678304217388618342974614133996546599376063520*z2-11295873262972852729677123283983019399199606454098651113583661897682446058060211947552106326335325864804706717099830647267331005910488240183270843669841039502288681880801909078334403036*z5-300783887901927725720759432971980687209852579947369209141495508768665028258896171870982023017518953125037961025816521470265548881307745213164399765630213951219913947292154960058368655960*z6+2376581771182097586220824300522877401221849914850296489782159588765432249799715612460890355581636726987084731348253655389249040733621801320260671215874377757481171096371464864139167022344*z9+1547413379428019677701551562983912541880795487741236046295479950343742054199799357470068168608831732948447020426686466113876279821473558118104391717113099338652222059776895129991751848927345*z10+6647841101396967947183012902992484661310363162805259189491864119386152807145093442425447455750841677402882715674201030882553230087557073916222789220719849815904884205451045259021114744951, 3890860365687477977275337753836950940622075600012168970216522317872866965496691475968701701871429150703836216767402844637230495754192376838009840364203454683632821270746577688478000*z6*z9*z10+58363771508004817743124402467433254049700601976660913188712928078099045422504818903310378640018072517235310253810330475793568489966261564656949977961659436728718306835425418734882800*z5*z10^2+207734458189289390572059642008458430398417049530213983830995510524776897526859934503549528419816133282093503533192632689492257834689955610784281090736625934235617192490485615728084550*z6*z10^2-3609914676025274038758229391597971263649890434897748048224052487234992646051156249333405290891997849249491704713230063497143646738751495320193828670766757086118793863293904114295473750*z9*z10^2+1445122435604872830495593831388747594690881052708221293050424909656940896077027979600289472319517510979461248207838288924797365292426985479127908139545761260735942247922111671976364125000*z10^3+270049131856142472042517675080313721388300053130416778096044613768993069942035193057398181603326236807475519498891706557252815664112401925574641414664449081041188305048432298032*z2^2+220703093327704166932949744858307009663821607869883906538001043586100740741294370287056565666448094372652205553662966582748677914628374649179229572322982128375394030767193086050*z4^2+15236236684678720842387225476769440766967632254702133585067615570943861733106365865046781783719197500182824238315391323389305583427055563628297931952046545123749121802353676008*z2*z5+217821629762646510840605447242212214425056174950976535793981937786400169061869059317322005341400487374001083434069273340122430152996835176065770214572695050246288352714386776090*z5^2-24037707919245891578917058624383180852309258133709181548968374539019697989864940172647136592118295137421004600956878452525397327507558025238735820210063930021757138847586489344*z2*z6+5487542602396314719840696095737092500432358091171421524277780345058539316982341833694328994162898569215638364498242367806911216476415216594139054348562671097611969508182919456*z5*z6-206335613067779137976052002843059263575250264836424858622002280506592494854561217365761279647932179671764649734145658700095945067435957948208174429769880976854514662763939434466*z6^2-339546169757912588402562456863013724303985960226054126405393870746174392692956693201254327323988622878468420347657732350059838084146441660326951366094534509840335269628800040768*z2*z9+490867409485150379333036518287865044392454163911794509586512029877989000269236930453853687333562171862393829901695325152687430281397150371861657489347162499395598091002354721632*z5*z9+18144804384354425963682573690442662827188797108162880178151535589918796164934525045757708410486046793001818308051338098956977812564006614648543909805177822726656159827987307900048*z6*z9+9830144127842676284240207177611383831285187637304074289776757622785954398178149661602354963646089687435285212971447835903676618756515934959186538722701873573547391447040000*z9^2-3223130068890824604922593488386888547304397322011733088313536002490054969475349118961587413393149882712975005016990574724657775209853000911733421549558583697790066127301643647350592*z2*z10+341993991148255228824403562747532874404952570270221651584339658378755640552157736261172327288868296662950220053929705202417256005218132387347460740516930281461265448301352027390196*z5*z10+2919756606291117364449614718286594665137159087610543220767292860048528707175940665843828437597076407294606368163664191278895918793179811328994373775898589071187109066465984147639304*z6*z10-43796406369615384095247649357950983470296476305994823118123010692657173694957176559739967731763313615907831925359291295484958519253251503423053750373323800640547605100845888430205100*z9*z10+23051134265026866788333927647978145545107521403176578492307246239432706220544313934744062544779026792197989964535475819897945785132526425131763365762485787657769410231753397868371609875*z10^2-14745663562242104688016030473740072528238090696327655841570354222275487236422291634597600801191911679385966037269348957851895287119199926696563901451244467668187868677163268204000*z2+486014201288549450076397512096729028706204950499216952620241004609717047490976609815040295798437462868556181571980030955735262397037892095096546761025341227331230428287754463756*z5+9128348950418218252169317380912899648307037244819093130447673340256221733654021236741992951035025566767250393567288199922101001497311725087451939342422068702766111895043514198770*z6-122961808543045401458306547558499519891765359114187551513349648352269089031201264431600706757449052630557821703596083110219580213685547758999347703060115622824118258138714032103414*z9+140668508564755952074212162530500798188643328771456907641389092582414679008866836949139374160675528125382099265022790166140350048081459327610583253026317382216671249793130243095453910*z10+346052660822617131561769456296816319209120142032904755925344152685852547889127111528520477429595246368098876761386487762303780685491653177160925578987965797315261656372128132790709, 3890860365687477977275337753836950940622075600012168970216522317872866965496691475968701701871429150703836216767402844637230495754192376838009840364203454683632821270746577688478000*z5*z9*z10-72351544814116341618201443981696219552252674845526260428236392910433259166680572358773854176802891327435881338187118105585660374664819366620793450937668536636531376268846701748744100*z5*z10^2-353499728672879294078583516944358794647077064081277536004897615654759073375010476060871089413111627277824172442707472940474583206532280148445758507916384145487693923237142014353031350*z6*z10^2-2937182321378213438482145927358448171277845302506977855973091205615251411649327724346063093152278510952238842284827934835692465167084897950546233704186930500429282564574467138897752500*z9*z10^2-1351525001477018069226525830090732151651941303609560409832069948578346735969694973545012225910048037916871067772477513533237945410096646953199520501178451808575058667819256886549396453125*z10^3+438758155283866399569128049540057010366851843654618561828476848274752835364475578693249951291917652239722985658442671220560665286344291906901576708084060217887395979964240293456*z2^2+75132537573665674358144937527322901124810772329339756129496805358636488786378331221878883433720706967193020869285995649409908344428791578085372888404050356816667338182441913800*z4^2+605078242040251456641340820153165920860200451013333056640822836390361847131094821299312323908355015577894458571485982883943493041054589958523139425268392286324687216664011308744*z2*z5+89241708058044852385144548568914238000172409519103928602935083395493670949508446359249590175230972883683285332131569052963299384849212257243565353442411497904865520032842767000*z5^2-740142420643906177228562020624307575976997883704646756449787814166338398567681051459273124067882066532412385483828669960129966656099012942264881028497605873791911899971305034752*z2*z6-308805162300533694476506256494942634903352079767193476210021804911434960566772189458716509284179500979709068868512282302010517105064060126619270721963576672849437806887762711072*z5*z6-116041877395975905843229879339174734520335976426110868427509381952093402095820365277313985468539355839534070221611660305953330820555057924648281635968053709959643758741963378248*z6^2-1433466227211289824409783221155016628661341255008751745206909205124857584864974018430468782781739698304880686488702497003743043593210898297082763061623328289487038318825138585984*z2*z9+15801349218839643275179991001174766405475578015824461786816046507810497138634035127268215231660921073205992162999384404422338501795744406775333416359465115791477313963555232205936*z5*z9-3314685054820469658366870209089911457214023084371750580103636671424768011915614623263326389041517667943111151932213076047037577933084934818734702140904492074216226210831412291776*z6*z9-49929216990763683017824936567721856227661944317836542063400983348432514896683175708524399496591704955745225885834791464263759819714883441792682378631803207625576151572480000*z9^2+6719777913952721285297071926182340654126935493564293028059788271688463521249846593425038881676712775586153451800389058026876363483533194874992162144333377584430239727897927234011104*z2*z10-122952674877657741809777084911829423148568730244288595331047057789810687459328961632655397704403422046595745757416248250889710423909546101180036860105918519006637175544687952970652*z5*z10-5271241125820773107620973081384371809031671565200585513711201439312557147139254520614141704500543066059557332545799910072855357009632652918202424977169184558966814251023665664656648*z6*z10-24294694772983644141423480365609284752345566411054238599442204550473043048449855343913900059068034726135079283907169732465901441732318257070760681459818637003282689785878042068877800*z9*z10-15359480142374911002198661832994643514246889417129908943177796712727409942701223723328143725072631543206779866560412858964579100246290068054223413702766400606975022720039625347543453500*z10^2+31117631315387667409019627691789336788876158832084751730740226892791325056141797267467390589894616082616376795837761627520314217895117107961849210785523427143633758779356873666880*z2+878857847107371076839565061781028151124987724614126813478439745104904337259291761480156207086924547670510636367088774949679953119536776286060070160877436091146434657031024925088*z5-16613269969391574062902050356488095446010181588604136790310113538722762428304233283585650338226103543255464309998328283580855874480222018098534551114757076090660212242386955997010*z6-52015019816230979945124778089832029690570144658352921553394939313192694416913459552315106234243613822749401404885095428331428517430648083402627113917071311485493154807991129036532*z9-48398269707905390988454922638635435376698331202747210572240040039912025025562259748735717398403190030934556311834027431144584522904503053816833976009804093586483428591707188669151245*z10-14095704740543905115037209570063823724978446389839610928609474982053718348847411325272058431809877145147624550433024852800685204208088179250061641822460589312207248370584939440798, 3112688292549982381820270203069560752497660480009735176173217854298293572397353180774961361497143320563068973413922275709784396603353901470407872291362763746906257016597262150782400*z2*z9*z10+18988223254976675000654851862816006905588251791995232708256564741332819817051144215990414964787597341600880045780203477013963646451720927526251784681761240041789732862595864453354800*z5*z10^2+62590278885846742914640815694583162231746801404930893576079560423804816266583323795114755583402804794337355588461154546803840864169397159215223231166308923304976873936370593374665550*z6*z10^2-1052964628541052602253215166237587347443661352426350479631107889285883092773708156072001113417871361463146240890608339998821623240191810363195622313916894125565253978935032762379778750*z9*z10^2+415525572262850600289828598476843639008195001306749096982152889028226652676853105317998051580862147179145340715047561241805017349280152015104279492856546963205412401376158681813817875000*z10^3+58913086127665844507130978517308440000909724276877588431273341279164375414849323591490939093228398938335550212672471267098034167881376956955219543455311794612937706516373811824*z2^2+57626582922920526324045880525049040724351451080978683600330688342616141743068596867644615527165536168433420318587093842689905810869580109396043776564816371344639072297025963130*z4^2+7448382926178246636495089903640163198994232024360461948715770898818860389014868675990845835215559879856523207634304081194369883247160191605010924960971762781515598107364204232*z2*z5+56600166551524963218437216251296200515113151134627016089472838539410242338881195088573816252257778668773238359874978551667757466230586384240433793160692585448213283085455692754*z5^2-9122276294774609271482869876009028348906930081309426214858779217567738146551787185895315461148521159661201632290163226410631992062386476107459879935013055704530704015079113728*z2*z6+573204090336166776427669085335821558000615699816016092584978966918858739140702826233752573817961908388475703305483645505433064267964640087329085090323691823072016751859655328*z5*z6-53076969109680373924434706193962392347136305330638602374952740144777587666051086145901305783436732760050033297034451345970538053172938134218644297853496339875342819484631262714*z6^2+13851909601451468335504151024931048128957367288935149135755288546954689159593808590125418307947019466571332005529509871650312203980700835239958341956135850169835383253736812959616*z2*z9+124689635701053107494256205499860965871592710397699546727578781213318495734001125884718585126773160787829243148093332913382417063073288498361399762247391276092083122331303496160*z5*z9+222123063148330432034754920893120364914593837534740875036405527788944103576551482139320556931248499275177349773019979311634543508083037525263128385635736227607980178694954763744*z6*z9+2827464194934497324161022297394569702263893298213134271874963544666478102329228429662467429997226019792835885581458489789499368014247327894583349044520757234525234278400000*z9^2-990988366308429845339746906022470360232196364552230023123112938136439086928488807471030145935925037912333260462091055550124700619168744802949484095495040124445956401587582070627136*z2*z10+108764833335615911363717451293476301249519692235114576820746190762116335560966790807337542098328501121172533787570605156537266368186398668075307914957100111595856678043478082641508*z5*z10+883884136975490651663905216668685546570461749194871331004039598470348616136839662990097143182213795562968695284185515309899511008113955314094960971167156003824083009476644711773032*z6*z10-11627316119460498525189582838536405811011383176684741584034178107195849810596161024215278002770668093063297448275414440264329203670624719654826098767330230315486514285912820038379900*z9*z10+6511060065084834372651892808284284027368240481827984567347801260495339150097859392263097851490076601030511257213922626523385422487370959437251783814528780606177238184729517785749706375*z10^2-4552561134322600716759429338507975095851151780157646396949907083321736472087755957282928029101823594678543674081227818739394055811461333876040159628573248784783049542959586224224*z2+134855130916298253209137156801517084251319237876086592342723341700778950310865249598623489673861757148934323824692814463115180040952116913510163172315349446402145264329712981916*z5+2772587544112908610378457275373955318339530098698446903354102989436538894036098624477981115739348621354861220767518759482195619699283401194970195521932971892350864776104304645642*z6-30764312746620598368171218811578999946904931712122809211108266075587068100722421322474455276808488392189394912200080684106769739364540031108409541869827385168551143511640490205662*z9+38794111489569774886856240930784820387697151182285389185935748406266218656904694441899643596439155325530322408355289201185349745152362693490824404117912531914759455100170784180941390*z10+93162218017999048380244344090583218625520155081810274245327694150378241503469638709561821330979863850371225587301402742903695698928747312413814636681861299755681628195411217857889, 553366807564441312323603591656810800444028529779508475764127618541918857315085009915548686488381034766767817495808404570628337173929582483628066185131157999450001247395068826805760*z6^2*z10+11214717464421652872053934609343574988033891837700537964177694170720074521529156059524100552342324304480565712953862611028361352370162812186020826476654365281142221382664871237848563600*z5*z10^2+18263509944726447070008338689949089378525331241875232867772059297779690611611914214072171125138179463639765982983577769080442537701767681928066144189453701582214194707409146355489608350*z6*z10^2-566118163663379295630294147423320821125428335767175907328643743656130600926176921872796812012266781727844026415397845179968564172425674050960147184715318139236500383512655772223885000*z9*z10^2+51802234140010219417797557981005085570742693876392297834951472028919387817420991761469136081180747515200192674735112455454241649098770378943884019662925945418945609712243404357606819109375*z10^3+2478513828407607291547910123251142376747128226648173530159882115596180083191538259393210923784687418379034974662477607107888804211724554138372030290934221187040760262329591787024*z2^2-1213633355380847961269204797050367513632494267840809392186954408938153443308083881123579866014577555468062387582439744711710714879342928346806264306726463045308925621489208235690*z4^2-17794193932585826559324130051264796060801184985323529319324453720755373486248103166398826107473507174739559895409305446485704682534182074943214164585144939498699122933405364860984*z2*z5-1628292127111086116500772572721004747907604581691713977780889001115001267625725181428698510790922356364930926833134948727289730243264099690392089883540615799752930425849658936530*z5^2+24474436153258473786013099949617225009803258343142490630152316472681049376889048277181432578433999413149686120768096464961016270805359445718193787537546895534249432399284435223552*z2*z6+9406101642827807109568907032715702117803350993372836478129240853688515216742081417973195588474407674616618352292713527784245219043319793629639015911663153126262704347012566531872*z5*z6+6453495946508091799277264027722278204301396825243551356546235316438399977488857561549393707811914640627460047372907573920975143964582018871587242492919935429275485955488371791658*z6^2+53900551434893258020467135733489987601545196147601249779287416952615835404194586991148249698735921450358108761279928974810696412440428977838022099658612942927978876451678954436864*z2*z9+48498167087428543117158488406111002462427783613209710900134110511516651061589310194536777543023239113945692168947969993376386861760940997307322864291297453703875532650747112482944*z5*z9+98753014467169145397031973058831294544139189318567058688192722393036108068425093965779466293519601212803886438466125670021560519711060395895616641121689818984950721567316553422976*z6*z9+1599679145261602626424449433716790884543672158363458369433529949015203340851820714546471683351461179018245572978849802567218907029918654756153302331478066525080755785646080000*z9^2-250766182202387639652301299755732723429377302374249842476992760458595856311539536159590061704259178410846414674060045468639945389627337224120574422935215897100697006518342831481202624*z2*z10+76126794651057798110145128366873854041756272522334242388273486106797629709007436959273548982584571332656664753580777338722313304717637279231316667884561992200192363124851167878438252*z5*z10+234707278636547768695681970585573116796595714454409015314900393116463177118933430918101307773706549225134437722502169278104658564038174397177966635060812994163702387798879367460304448*z6*z10+184306201387755270108521480715624082018575690437565906366084216080967418729934041222607097953499159808606678565985918370819663202115583146827956197648492879249844472337169797837298800*z9*z10+644523440572137160912601345604860574912565638613048606277223813354027391077478270908273197273625425872448557031908748636712497796557568405565583522509171312588133052795960513733600311000*z10^2-1095996693992079884337705411687500348450070030373067700755274808188866094915230892682423521287293577562205233764185808758194302128091246431690470668424717324565698876838837614097440*z2+129919395512411613431128386515874864651137853024156504094121839164290699639397340506632497080351745890302602608753036829156441794679330697990289391450689202455420327811299193697092*z5+665645672950343825672542194178932231288919270319022759387967803158290782834420127194109590544448068534105297518617389134823035583066783258638307243589434256915103082516532750835730*z6+899069411464410578416873676592852921580393114192039907140937829904630516900077039446604602372776519708807327714479055385447680633515573812323951050906836183496356411416366085146552*z9+2493576002034470930237317830680755118341897538327415051556816444843722840165655205616487793808094587939579012341605719120209982927788540989376058022555629062153862620816947977765091055*z10+2699827888834039347528289096279780069042608960286787775079925843140045442513027847578435983586721972291856405229761720716257505226701139022259276592172574888479363549846618138675468, 69170850945555164040450448957101350055503566222438559470515952317739857164385626239443585811047629345845977186976050571328542146741197810453508273141394749931250155924383603350720*z5*z6*z10+942552007310979398903933040137487587609237777752881565665432807814366845913125743774510129413112269429363349000019187303651026932312447260572172980797555215434755715697062689789717700*z5*z10^2+886419122163250268756352567403298458064370684488486378394865149270010317885316799458361143874605135181081131475547434243504030460192279437757646231219766210824401032518954087304492700*z6*z10^2-6240611020845546930156777675075335560734789031033756854839127137250430097295874778548312011316843434517468034259056209822592626257463516346767117026592278217583678811600845727648870000*z9*z10^2+4005231201729301914698577820187670049176565845367272469419757089255441112159167859436567327761658498618347180856142624273876522324358323666627061478199621950511159113374478229163959515625*z10^3+1313353427493494129340902514047720549985499834388928457181990197887918021299349313403145024182300076159411100675693306347871471212231890451952731834232186966058632894085403359808*z2^2+118705946791274698889789145593192643571775252462521968760806664688712831609568820488866464118922183356489904683161624605413126226944919535004243970829426529831497472989181281810*z4^2-1575977188346682935393762836618184642716815499819626304618612829419376213719472821886463822389699433135467956923888976383464924398569179519419643146769882654719681944916634662048*z2*z5+97165189705715068618577513096597206278739342327080308909984260280680608722999348582963988279661144508901291215206125598040578951610549578749569400592965593252053918551919084890*z5^2+1510774109153413556444165005195861656117553863063258998135916418633191388396724144234995800059497597230722270604117205897599384605659762174920477145218764816904172871488233749504*z2*z6+1117678497549326615533047479563436781723533615114109250401150628857039704309505678901581122681456115586384568349465001975703685193875163591969767594380016382267934317912912275264*z5*z6-11512881902595466100521445800035159226480588363202072587438926299469530493734662404587718988801754372511662127514497893293272001307543308801389986346626236549304722583369159954*z6^2+3647261099520645182355208257335990612973180929037767272383231743280412240735721212739764119823278296999140583974009462443803020699991538864627769407284977464087395462547986626048*z2*z9+3257985003164428706925616565216230896621587209719569893202006802946387215510996655237706872850960451784122298282198053978813118033605003835290025630179140883970890124797332235008*z5*z9+6596614394100352102723084552802388695295835737175750797532100066897579858258638005759902374864666418863261021918964885087142446320574959540813186638028911147985479707902256349952*z6*z9+107375396504945971144369712592778856309069587456675769924923675009061298789343929381568804176067319958319473996576683634687472777646279774020428690657010175304956782018560000*z9^2-19102930845969318881066242837249015217069699701359312794711313015798304963616225933893488158987234343531067523098948374587184369990102554976743869416124794493495190058182319648671648*z2*z10+6088789576664051654499131469653090006466638917077208399464077875760644110958103214579764877022027397611181759560876893615797229529296234117783035208568502510555053735410708843773904*z5*z10+13148953133297500417624835492389586161625396661981258013648438629942319920198507408807172752185648030934803039162287610001078338616459547636050494707404256603500127273623225783062576*z6*z10-42611886861711350046755322243133144377788281460533722992184073996535672222395324664173221817345379413443519649564714122114003663537898623674555118191553918982962198436208590462898400*z9*z10+56319341567539165468327734297301984622683240151899670546896088640167273016207509102028333688650616743576119134262170476084823258376210874849659838921681327665650835041973384368041838125*z10^2-80992536715487892316841437669009582999339401117329769238256524403523401231204013927659002475901541630085294784406371717045125267946329129035894335502871355537916862103026094473120*z2+9179666195909249981158708648207730951551637046390945637628525425241625003638287632912748121754518398103645257660787800061739552164357975781957254180961520607213673772854818344444*z5+38990316160231390372274064303644138150100096103195499868347700787379559258174708470969989596700168964916228630160353944630344366771336672382245815210466196732850691749517814790020*z6-61494313419178920444985982560477668083732723695892397805860548946111461193857437204731460334638380463519538039434278303613209286937627177377660007050041173013063600925261273794416*z9+271267269746955766212785531839127077391005402767288944674068847624475487743376390729558048563141907175733502098939522239072895890597523296918477624542863985371228714565335126277351155*z10+478429081518126770579911410780055104461437485192044037467756332292175935737174357036248679563699993911806047678409586921701394559264646921514823757239638944769163971131536163244321, 110673361512888262464720718331362160088805705955901695152825523708383771463017001983109737297676206953353563499161680914125667434785916496725613237026231599890000249479013765361152*z2*z6*z10-402551313070398337230587164052878633718210999603909821480861115104888394274560133063829492059803714545519729166531085732805275464067148155066636684320688490340612634206092969786137600*z5*z10^2-287592019425836136271203233776380208163550687757735199825039376524697377575148923953518779406273251628357349674892483160972309137467507756733870700166691839541342945446166173006752050*z6*z10^2+915915171048766371786961602604253615372174761500578199978929991940589248465074991368180827967941967837355464132244787758618605466580095952706141557904597298057692119481574799996295000*z9*z10^2-1469985186401391346742397415685126235106516032613670890500335573253583552904192449407195327141987057943725745792280580377790992600922004346062595031548488827215606509377241955251393659375*z10^3-688520702264192909197058208227128478548813822632584989533834133909807162258505002256945669520840867843358750427474231475455617882032574057341341205042730386473996660336926703568*z2^2-81372418686181761046707328330867418525243997425242015227552648107445191167183183246462393382638830035793739891151595353951820065503380528401383297049189346767452234919811719510*z4^2+692589382358426300345361176803068872926908142913546013014321825594033388907123064838955313724074829079816474017465446158272397875636996352746782987709011343176344239545348026888*z2*z5-73849846989962469729675026775811926839659274423771024671328964393742629772694800000971201884511798692006372517841437443047533222193349861557667408091268807124467779440691956910*z5^2-51731143306119901830284225056183245434135773042308041894157976799183720860445329011841278854001721722789618740087504246129224264600226625105445566910537441083475112675792651264*z2*z6-346090107917186934598025826861946368664184802404551358645423060506041611544068552132224994560704029223692749611968955406410952447059006212212502899364765155597555977218236348896*z5*z6+50150249615350468739653800034897925281821392750879024101852717147354924895390945985736612612414680856447139277087150667654450717149059851133279893496102038397909640134149379030*z6^2-1392245053247004443539952162398500000588854225443606461391179863771735823370407629442369256676827231466939034860676505735945638189297379246224219585140010009733845068409244812032*z2*z9-1272390968901626781641217643907651452688168095224833000469279766804744443903532033286815996673984464881548549583250828402736937497794568462572034197149432688173949122232815478144*z5*z9-2572151050785120021854935167674147469646994308757490901204960776134823785115251903448132222484146218987269097976840638128489242712646403346399446115911676324604859966874060567936*z6*z9-41744607525372897691990309851355812733003643767749172027812378924698855111392242503067753773811891326588641339247624245841468812809461894573533843039238883651048293253120000*z9^2+5905038252630494197817640085832149493142086957085780666145135685337754282233616067890523640628794398619560803149275913001080418786202644452208877664579965573902858920179844779236512*z2*z10-2814533164390787718746376699902001830710082878054232258243307078877428548493606891579624326534901728754449621531288954728668549013016791493939752672086265009085104800303161653333308*z5*z10-4177803123454133556068982970982112395660050820362677248075364321462149866397792255451281839064269496248058139260754584662072872446566315650714315392525461601365281870597839048483224*z6*z10+3531826014448624299946499265026229231537281691611793708524942432880159799522570231541526404281196546518287279340644826352956981901005200510252482327229612965323765270261014257626800*z9*z10-21921439417166130652174664278171983487143719721821545346642358555052153796728206537557987222415919735671003552695631172583099535398965519365759796854537022946323355541948668056393534200*z10^2+24604470833460016677302846046539733499583040786241540460100024187876008415180377107943277968748121601889445685774580094637803626470632243099153825775418123031418744442164705863936*z2-4796147511142069795739985062109651480501391720729779777736676031972072895768396746866817199672712924274605675661096218200191683065153050092215935966690250194460373201688936543972*z5-12209591439136466569202911012948947286900837722261958381224635001119382408143689569842768818600678646725501754081267895884747381064385415329017762738354361450685769115459717272166*z6-4189808443784198598203050746595550980327700568776144035018822110340211561752992378495148064020456110775279329940483267846298523294440148557079993078957494820684707401976055540264*z9-114718303583258552005879050445509582736488550664552638538311740617847472695093579370297928520890318776614549929598722644027484230745448863793803504349545791197372391488626065075005151*z10-226576324165219740628603154469601206113392837982643420897664388059238146408515723192182593531647221852688560913290194631614657902810426482957158653611665146671409971355235469912844, 1729271273638879101011261223927533751387589155560963986762898807943496429109640655986089645276190733646149429674401264283213553668529945261337706828534868748281253898109590083768*z5^2*z10-6457403833634355740314664708705133418733931984311073047128203565292044035851515692335569885278416559579412768141624136002354571628914213267343931512082852431301752044126970611218500*z5*z10^2-13862836579835718059701727588435835021741580669411282070445793839022541745037584809334048673528041200481283288857132330206078050265925172058527522767891652663645777563106627814684700*z6*z10^2+333143242583550892907126767732003457345705439403430088185389403971547639607713149480909715088259588531132717942493382852390550032441777084661183094667592091798112856007876451458610000*z9*z10^2-63137043443190745713350135297086514656730629414702758668566510719366637937446763124424096768615605749834235414959072897882903242801399974698234721148205307084911979985666116854845190625*z10^3-12223725321000785987835046046130034583382923016792648794747345879110709271893497420097837818917110233063802381794321392358263877419675497689213504691182596354558420175170016992*z2^2-4078989233982038644789000377367629494257262187311348805659527408987389711882174116516258967876582429243190530554508492705675715860810373868024731453022595009575067609274604002*z4^2+2399852813219317165314575166230460832607785487026424977207173331873687597686184094257403976012213431063074647569585378878406648328868182808744372321465124359509575463238133280*z2*z5+3866872124982029087071325481540121620928803856783793487126933768901302709333953718337000667646081458256665013145529052786610673632383633826184438796123533370778427486664344662*z5^2-4309496943603399173413167566698725816454110801878933173951004021083609002270467773143301851992418336351475733696299509609096568819700168178850239529586707359735445612455247872*z2*z6-2275450069558509624029184827191678185207044455019402179138804294206009345824067410230985790759051105167401891968691803175794332502465194649875652610374386404617719349902369088*z5*z6+2335536629089220303504247011265101799172766955127143275807558159740155327110114233546415268937667029490486926957724702288518896054848160078563225571170740437505687648213756130*z6^2-26554091655029602859922361636180574770049675238210694614940816565197501994678290980956841296469973798472909160905141306600935614014943380879906875489975696067285139240306831872*z2*z9-21469884195671658890605927126981608624416368780534494195575548695531299405222015808175067224693313454383421530200996882871182702701178962495850196071997845100228318841773150464*z5*z9-43748139006328287526778798319987946935671672005783797910830069504048561135005888670434062815608399947119425171584205639618288377810048950069867812542697465521356284418531488000*z6*z9-721487877704492468542217944251466776610539162833122727802209829047766418913507547641132912748194393988774898571451086160153691648199896354573949857912693903576991170560000*z9^2+293842552568157274253686136844210166182480467808126632110965882974125541864217021794898261093479744944204833444362671776273639564201301582264416301828147554213930206920814619695776*z2*z10-24249126408816993279218669794573605382346785936151928593721314979991354110375272812125806433920666586369798919315805095430935463519271516004350057450999167309513768894658425736080*z5*z10-208887311594433051826654909714321015446561059199785485705980185621330809390410997616310355594746574644430116074444665132661674322197071170766401502838756324839422842504118674586512*z6*z10+2850537076516439696359967641194992415314020598134599324291206259214003414111538907198200148426385716731188166867050767286225211151117506594916187051628075019161111500615873131338400*z9*z10-877265921477907721657071311922769601168029401079916816829009208282415711928743012844033899183345129272610681656274268561632969968916723713827704582940127316207313374286180696368469075*z10^2+1268351626877137303103932307242119770468194163524520325198874086119665796882351928299428118507064157022676907801819497328325047342491156578352686246628391027765694952862275313696*z2+7077972178775381195119867947528532262123326964976843405605387302861601884178705658401902539660233501718474931713830910330010664837850015344580360289173223327029583455261794436*z5-631811002438207768056532855575595013725234249449902467488119281114728379598596139921644115577483313451192133305340966924253300974910184471110696067171597507649536800067504043748*z6+6057298436301432747080625601949078754059743137261273280419515477547148604346788876634994136663198888275571662127878096944667661285802882068224652426521263872399766731674951757392*z9-4388752963810934501362116813793134952219877471853195930698481944249877818275901914070321587138561799956099904962882082659902577155135342446185007159099971458875234372808282346733431*z10-8723824909357488418886549972296579528285687407351340119212307845600463800961744130396712786003661593675745892223901982387755126080657344241281239987972941276472174996914321987591, 361998413221820632094930223959909313319151734131410334285269899049167985162845547198281611460776495209118553450*z3*z5*z10+1186162066332243078433218283177411918369599774331573710898518744791265837649140209793570429808612135652333805300*z4*z5*z10-4519929332360965277922957799122815613805760377854786909537988826271469728069892099004647025801013588229892400*z1*z6*z10+273626820060114602722546751119301918151706182629267636515336476654870112285596064241679292400544296378221331950*z3*z6*z10+844638055406819100056681946720338758033286511987077241519601075964673829743107267703907715750281243265495710800*z4*z6*z10-263512741113176272353389189338626733715296378393705549993191793909709896624309890507280833696489752115885720000*z1*z9*z10-16900680384866474741902127765773105630030171123165734740657696679608458154360818135586073395198411836669729568400*z3*z9*z10+17310782359040111410926054216598510261738362820967883005004740992484641453076135366677781312667432891012485250000*z4*z9*z10+350769394775909935025485024565054886834146587688578566245015007120670359239014142286189143257507758429047692265625*z1*z10^2-2564032294396564068347108723030438763790655191061825216103169703049159424357595309564246055241412425898217005390625*z3*z10^2+121341859743710692868972341158270200363163345109402629516579904862038245145465297233982684687174868517082048998750*z4*z10^2-1893135253141210671352932908312214543161877069856314262126538491832822156483856976753114487611843252605632400*z1*z2+12987327267706827881901857552150633531151697403244847181217423325986562306853706325810646814627858245416009248*z2*z3-10335739478382342016289145664757490339190247043573979572413972923388901530969177190692516019236487154783313424*z2*z4+3046744616259109648621555270471570944754461451857461880507366332609538528421170997070042821965059815738653112*z1*z5+4077774458208489088867860299773255472893093152154760740744994267514697798049542730711639546126346320553453712*z3*z5-318141878102828040924400836529161015570356115468265000136262457375923664487511131277629072937596455889814900*z4*z5+3820835621715677027941789372796987389153501858829020258694899533570508181451329082189811956342671300293510912*z1*z6-3070475119908373414011659562021174362972855470053943771871619988820166049058483196466918958396858809698918112*z3*z6+3991851104888857048498940492098140517271749363692775490823682495942867261692661963143243648490468039801827712*z4*z6+753809894884657289392697244670197856826347914000738210088864963620744099019011668691450093989463759558062400*z1*z9-78162826929489454522869737843459242684425419204884713538052075532548336267453866257215065007323549805539597200*z3*z9+78063222065519149848469066398633253615648262040855749293497721218786096669300729749960768810043385550189096400*z4*z9+3119560346795736433205027447441092752345986686204733139608155309258354425831163687227661476063909075326100643350*z1*z10-31127618370990444036817454022791238351769526649589705371671723553286357690261796531999630181705536846507975853900*z3*z10+11613987741543105250193640998285933061171472021055507720249274216424882120229793808155483331747176253902147684750*z4*z10+6303095296601371203834691848520775032928294407511204851249968937384200374613882930132679274915297723952895725*z1-72961384011759368790360297173057365718178961220070339509019163893311138781200131305551338593615331257826878327*z3+34481372739483450584409032477544501930237335216206597642864294434781613992278527669315456072503164435681843276*z4, 6917085094555516404045044895710135005550356622243855947051595231773985716438562623944358581104762934584597718697605057132854214674119781045350827314139474993125015592438360335072*z2*z5*z10-1493402115082891502085487350599174358046762247291644474791170183571229961617010041148455080145308806990944258084528548246158221630576179893501302780214042296417380631178541288183000*z5*z10^2-4533618208774099293681326480623259460608584391012116945663823116157106111573723380455506339133711865176099714916501510778302053392534011188994648598610930337719586920463085177168150*z6*z10^2-144398553363881866083720994629053741291425076303156034872397724166337504663282942753048287718562505510525606682346552140601930157720839243722114987396798504470926182314128339004145000*z9*z10^2+1510109742677404993398195164169894176529619572939265738548162858160739871024672346493121317327996972760114646193811906627686131473725098360263059492177424821647919010589126513770946875*z10^3+3463631890443820144632082843568943371653935788331447317379035789215535135654024683054066914551144811458096254172450056635123853465510117857285182711131288970585140600250562768*z2^2+8889150469401698848606259297440854206245339414688514442932019101884448340294023137029642778485553438819353615542137698977388817022687099218037222357098668134384751258361468722*z4^2+44060348993524240958164260028626666162677508141416850557361802581518520564167780460398175876734240855253029707084140553911035118041272504578945127833311061515085785767942054776*z2*z5+9233809201131635879039366932936441017279095184791045418905966539118932549434374671918198317605819838951083540703955363337871041232691770576132347695799323274293144390605874522*z5^2-16867053227525851021366982223927763894575211707137133262102796518858933088341608858346860526862564851011302693893106508655187171104158564875843705504774260458227208422536756224*z2*z6-6570123822827543744709395103274796125638800490119978715801438895841157110652592032446831370561060517463239917031581599530755967545938043205024427479555200693505803247606292256*z5*z6-9574059620346194528240001972715594318462554714823545737523866965963445324419852983851834512712083451948289627546553485562611995563112435542675640493405260516151068366651973554*z6^2-33321367761021971995050784775142430585501689611003738181052321635473812552756280803272501449776673715682096301012691283540521972367693868972181349969978378766949857249857096448*z2*z9-27469896361547966866149384165806895497328591721419369717660938001840441262221834120483696068108443537552761631001811307652293679621423214068868128727049565442193393925206411648*z5*z9-57081882867924906978085069701547609476271006584245033772442136613282192710953084151392585330956579873659302953511363539954626538208643493314519108199400761548932780305714616704*z6*z9-929262800595081582632020425541462140599899546672761123704501139900119073743228698115464288457409468818664386245874155770845999876432077290333989312532262733372756705280000*z9^2+85747874079866815456582284614744426100267547800438611013842741395450212222108047549629508919959360169300767518214150791199339113809064511229505959793501009467730686789407184288512*z2*z10-9983129674778152619892971946632832695931242363686199704063773907209412664805356796964675657309814575169988860789131680366340860865523050651329998626711639523714727251826580781492*z5*z10-68112892263383704261342522223332199088253053084681660505822698327867104725366128824766198827913175833966430098762017767266902071478100207578502913512591844210865423852301224468744*z6*z10-1438612948694563928006546415158153770060805710858244129029897001252621912668751306492754522908041507964730883718047546996140141778033631401511561925918024165410216572432882592110800*z9*z10+196035433246139083122105327336725945104775981161799599804261025789108641017115547370343184932370685858151253596377401317944442146381845955243509868465759861045009428332988964792839100*z10^2+397446326937706731569764818219847221299439391645127369167866002734746629899849394662265216842258472311929359615751968057095173250885780215430646375606241446051257802387086021152*z2-18295895521688854988839644161263596297793955932054177798832368910139091355258730202887058211442458270262218799287627171561638956537796465298704316274623887218149220636332096852*z5-221697208381556750783044847745309031041208108077157856403735635615374597670159508665113803072853165547887377850529326184266184214920882531772153927887568566388114517833571244018*z6-3581542716111369282194833993358859602158878159612007207143762020420847907485807512104403737422416477684124962982357042850922757271987927310813072453498847041815350099457823883496*z9+2548008439918657668618570114920282811142155052881300061235077117013186778282743619426984114598057081502209058115020224642318394217063405424043359185029216397946407856193992100743419*z10+9571280022837465212120280654431093251194520986475778618265710913505663831294196535790584873767776932432806411211738814946277537987928320947453813968855588866967572162805813669324, 6294428409101017150866646734214903139993410353076962892552273004666932926011558374683720660079981698696153407388600*z1*z5*z10-31333620122418817544696980964993271619263380046448970509487478932443176306782816962204144133723264100236726336588175*z4*z5*z10+10512785802991889473882488323486626425907322680395453256864901979945486648231917627639398911503216127980058807514800*z1*z6*z10+8171833696453622364352188983999888836073640946023506781828799131027050061924810472281227572181188030432865966227800*z3*z6*z10-29736141838699142125115325105321773807281987517907985780543796258509481074676209449146743699878344045156687117919450*z4*z6*z10-47506417577237591675678910741306925297097123510867698885797170388267654668366006348609334272822358604833280606080000*z1*z9*z10-53555855789184104417914598143330435857209292802892411299850397298387678855436640505668836866043579451254329997124000*z3*z9*z10+101614977479384173435703535126718607069312071633193206472710068429770871027618474452425848979006413354489731518020000*z4*z9*z10+10601939056121328646018269684757867483167542815383479975817724858332841722077692078445720033056780266022711046808046875*z1*z10^2-9532042330932507010042789790248749823069138430980478532607437663160146849614441857419720012545380267129495644637968750*z3*z10^2+2345674824338561846191954787101344084209856111215771778119344711414315185990177474708329968974443494081679254410991875*z4*z10^2+13822808777562058539995117462026815651560071805300904321737468254248626288210606496299250324862362268291178302200*z1*z2-254298687758146955557692103375436178711103590595815282396487108764972833796780311867844920230930357562058461271268*z2*z3+235492631466596810751934833975285331270929474137877096523004805594325416408741940120725325399498060420682467321484*z2*z4-28635144929101557079754490820108560291623129067671538361881289331040930164827342796643459314922114449045098981492*z1*z5-54018932964887266777545569300702919527842226515368017400352376766188801253597733758567042234720710609092593087442*z3*z5-28483381252890480306086383656205169373070776375276601185277375783139068774165380420506224773946896223898687900025*z4*z5-820440194361622130044476322744362057749092199438104380174200093912497423196602352205424425722377343675259431242*z1*z6+127425365370531023836891011172900197333867679939933274675051267863525690083146158152777167339542529195793805013242*z3*z6-173781599490763929206123932824431079078221104993077780963071935340857092429939418246521472827869335598637557375242*z4*z6-204666828465416464979516488590378260063857597118219754742252476938735185846748914477887705082577844336295827072000*z1*z9-248565934799687145549997472942599344257574677594157957151188327825506904205395943064135838446308184553946769680800*z3*z9+455699052237640813855798106905660511992664052974443867049198887591031314511442799859154613538106010626078808644000*z4*z9+74396877602493193637257987808318023875653938830261073814100270801466538668369617177573381673871489456930840999908950*z1*z10-96301791579297291124589633851009391869677269697387290102830612064975504764366976747275302473061633555337549546937700*z3*z10+8654728886380782727551069642471062098655671425639287375863036347074744059905190719288732178394080033793484219812850*z4*z10+87579944970021329080928982018164639753158801377867693146342700854230526103586082911234164607174762046073516501675*z1-530441234601573303045598436671204300467089615602314393125464091395998791371561405515015108897108008977855762588618*z3+315342655188330037972217498245041022398063040076891321196188445749466564572732035793649012277474032288636986823059*z4, 553366807564441312323603591656810800444028529779508475764127618541918857315085009915548686488381034766767817495808404570628337173929582483628066185131157999450001247395068826805760*z4^2*z10+13281086691184646708954627316129217682028750072680081339258719311613528613001641081071482915631417603545977798759182334549114815291415360431570884560520878059158782036785501833438483600*z5*z10^2+22699617650273876849112891518248556585482637056086843130314713326266903970023941353059066700667152647793776635417860114746387513786863736986794951475179030434580843527603267256188712350*z6*z10^2-107171955790399665025910859821664427171751168944864804126653253014551375275394384755763905640255335111690313768013280357944944574553794341142538737478344787514632614306033120238979085000*z9*z10^2+72006088041831258046069601276072770260896495289097180608892755459116711957403955961284847047137741355147148007522015782776770686795218370847319130430351643686117443307656561751157280109375*z10^3+6390105931127858807655124858012753443429663592021821144479032796911607050197457433824519025838162692959451736836660452662533244986020713398920351792112652020499454718383997224464*z2^2+91643199493404405063275323707273924529829632098822225624094361937811264494211836161623003705928821889758582195002972954105514196116391290961649758240767357755096013478665044950*z4^2-18562146832816008052224794104458543527235676341171985312030749186954953517507682076561195379797415472679743782631572767726794809999419893442012363728013779293742187081641567510584*z2*z5-2865691207105335424363596726813843666604821815862527893661507807163418134612590371296538724437668423007063731039704245619005145805626862514771110298300146478402027221582249228370*z5^2+25853475175211561521505313570960817271068573799743749245816637759427804257615597964587289171071573280782158355550912308035927172827663499535425864187014641889364774995270114542592*z2*z6+10134245665086530189258246177417039137069605218979045175453658227834438207405782989247111041517304028270186957722694904800499405444108655917599224746982956775740374538981324640032*z5*z6+5706124225199541302155904984117445628566111399602865508287816705321550272813621006814540821751861191190504230746435669188649097227030607646447010310145298489273665908059969830058*z6^2+62397860764502730935642291457067771527961092223828672056068478253479036042491640105054438913606313065869439692769574192922995808925210859719592299815405165669510121008577140635904*z2*z9+55368530030043473962152385086745117222241021622980749042718286094086666871260355253152799054925099419348387058612288995895165326625318265305994927034336764135948594680114520631424*z5*z9+112752418949194197405601188521227437563554124360417874019658344634331647631626978340318366394514289195882102493373071474699412800610276059917974341135353007951784732581246629582976*z6*z9+1830555266127040216357959175877260253059044690470057642330237094310488594904143129791634215430883385094653540521714150138468088357342621589616966286010128574225392960225280000*z9^2-344795799024197967413480863545879976607771052072850364752501843010316029708088983133957505254172696792991961376256100437047510050171753730445187639520223114449154672733003509783850944*z2*z10+83886515101879235959495102701137407764107244021902859538264306900394863024327524259153807041439184640295000407761834969260212653043804164352708686268881725739236769171141864113983852*z5*z10+301551218346766345280211541694155841739495253398340370740814052515289036123864950155320621564025453111352074866324462120556394347141237171823215115969215018112317697400197343327988288*z6*z10-727865663097505432726668164466773490881910900965505877407101786867513673785758409080816949542944269545373534831470327160772404366242018963545223658872491126881711207859909604190989200*z9*z10+925248535445067631842864165420146847286335046958621987662506760004400418894676035018364045012295867239683975161916514576435048186610919993990448989050012053774473332567538336571510415000*z10^2-1501869214592763821330963750004978674999892162700914204818914515747159149917583509738240519209554107809461844260768047903258317277688416536763330267345802453450721261754765714480160*z2+127654444415203491448690028772665734327258388395363914204328115227374987036460154695943888267660471169752690630604610937850838381931218693080023676158153770990770861105615419477572*z5+867825193730570311450632707963122635680994230142991548984165973115003864305970891969035707529242728838486780176326498550584091895038042289393729985084345459362954858538134044835090*z6-1039266088152047900648926516030852279718724689731567542593307122910457036490895401076593521359447124539375604166441935636845970977941348449507937725579968255671568942719618477218888*z9+3773469418751970675400384402971775872952351910120048342333401952831751999118049690887992247232548631103008222993171094542987431753297694513338945421813109379117687339451707842688492975*z10+4384718244699553016924777904101063917205971871080199661699609116648356144190615949474286702131131612734559455749793545939082471224652324212213141018061600098050457054069063521093068, 450*z2*z4*z10+450*z4*z5*z10+225*z4*z6*z10+4*z2*z3-2*z2*z4+z1*z5+z3*z5+z1*z6-1*z3*z6+z4*z6+450*z4*z10+4*z3-2*z4, 115653662780968234275633150656273457292801962723917271434702672275261041178852767072349675476071636266254473856623956555261322469351282739078265832692412021885050260705569384802403840*z1*z4*z10+12193109687192304887907929939327211000033441747445673353660390411610799358199703370427720541538818268660112168618149198530643762868179471802953202286036138948653733539072270142912704871600*z5*z10^2+19985662753175097420691153210800139776505201640412117705135856631454853140920554742706169832960554012110574118618757291587043316749972349155075878494621862859469631467015487410887809506350*z6*z10^2+25779235544938627913581764221004077335969730583016498013784365336297979607604961794609696826072619257830148432168032067503688302618009002971137308257555389033193349246061089485276328515000*z9*z10^2+43391221223546903024979270069975479413462683027233511983242923621787685949756260218968885304720452911004446417349678901528335678444603491700424048360493011017330980111877292729591088975671875*z10^3+11088657413965074321278124632366306754282859438861798333301947226808051323008792710427593190407695948488321152023267953580539802762199337263990693575895976210105569609913797735659344*z2^2+553366807564441312323603591656810800444028529779508475764127618541918857315085009915548686488381034766767817495808404570628337173929582483628066185131157999450001247395068826805760*z1*z3-8715715712660986168124295214910964492007813023406685961686531729330608245403317049737138485266105862370329335829225809041981440474142310519784190251046454209982288948680632693841730*z4^2-27388396561715955112563327714120535651353599031683438597443773715368951028911524927746669204326591473746837749054613178922593456373984596973476927769696630460334229190378318124122744*z2*z5-9789065407914906962261992906196132210615744362112262505712317968804758455826030717292132902387748557705197726155386633730011754669190206458470553419735868728890752619996519407313610*z5^2+34568012474499980134302081843730873711474963875160510790031286162371241871933754129315931415573993513636563009510559928861497101162245858644942555759543992559699397462137180953080832*z2*z6+14251001622457973913210911986738792788381566409106050509068692040385303841890390412809882988711423084569661205330616910554809083169154158994095282456884663614802660973848050406115872*z5*z6+11275736047286279384013950546711379383024092127480929868834527483430006445765665979225845138349759354093689876405963758600261211199013330421566981783746206350346562481483293275371458*z6^2+76327597411076197429336536393606740674837845000796574669438979381789907566825294333673778569902289671014507706477440530654432052586569828443910186490377497291130884382388241464383744*z2*z9+66759663652031509709105039752437216901719501381964349749745891310441941825938102414140560924642407358978448042893575726557652999970733107072264183564647936916065006016497372807428224*z5*z9+136262554766147661416693332877666667116792955923993056677663760423675451944526586225704302353918401908384080452833374721017234245146547027430117731569082276895644279617053047814187136*z6*z9+2216135625219275590909590075984966214748213692483417091037388860857200100258603204587845870785978845318014288138830264925949714403856443140095866272095991595475737820640788480000*z9^2-359458812719097035798152389052483142565287861010791178853062448388177278867948107663850122867727552007690460708895073087546266587644599933547337197400679584977095849630449221674222730624*z2*z10+73310558138138613670544733924182375059052152020848782690342608022645702800391942112142426756012114976391100511199997869345714166328005724767963706846845032947291700498389763865632364892*z5*z10+282888498247078279717912776722924174796129860034057844681239278942774150708376411676469600160501273328454053507951519738075060403682801289132379407393632317501193270631321574066497601968*z6*z10+522695601196711098858123291325046768548469685770583429088636968774113988863561459973174046069961348370269405078970389511337761163669695657278081347602475287537339646931617432130143762800*z9*z10+383525113031383026422374332278266356736843338481233263305542229911558779752713103787849576728670074136711159069811234103089184215270593041755158405945867073630316739510140566731403843651000*z10^2-1559316690458119403957455877730712958722940285983170367839344054842303049610220550744825160802134997596344135582551542773870102253179664391703412919440239551248543694283230490065916000*z2+100197366479787414761589053462039910023840569326576994360564295832313679381224919520828524536616638872969498146148947933321606075137520672339424386595218658983260251686520969633464052*z5+839561123057200615019736634039217837530805827996029176870566461489196391159426155140892809372527255161583464483489924529494897003187651088327345441025010098795513931660213574633435090*z6+1909240029882628996926278733952266044312278944354774234910406085386271427159843108588474644942961154709613266744432236686864435060326709505220567598216562070622034303672330949163339832*z9-99754173612489091623536781494396451775994607160250541196221683884995066744714591179950575173207993847684866155466382971272625867246151544049669664601070763145292898064376539644149553805*z10-6054315337984613903082382768664401279974537760958109993056607449863756865450562872159956145863868499104657057323731280244075902074322242644903683829277089657174229391455247735692762532, 299734686147667483374602225438804911428257635860807756788203476412711091714836113080177174289522938033150162256600*z2*z3*z10-206799914729720111423192630287134321777313582347227411359912095960750353710392327190339486753064901587656801308150*z4*z5*z10+5666636077338553784364774196068456403431852659228896595421455260868991149656071095783676581266809734331136861200*z1*z6*z10-40683833019222162139601339614373038319984814220570263286487633734287243591765839786150973866982909208580316932100*z3*z6*z10-171589460030848439322321297126732211747183613910445105248207946062465253939667487510353669222579940329071621757100*z4*z6*z10+44666250074753809769746724186066073388335844548300825425465657543847157939308330171415141220165057119307543640000*z1*z9*z10+2003705617850922110379088248219930889419726159553620619736563354610965048907513311296949096833520119558847143493800*z3*z9*z10-2066899109488747036070917094632073374783358183010844737648244161678922407701819079296694906509295119828959800225000*z4*z9*z10-64426630231878841489734383797547968595175642676572574959134219665014995817134958361116780412693039443921620291953125*z1*z10^2+469738918221613625835713086374613647280312190069424097787720606729643305001172234322737364942217536931203420773828125*z3*z10^2-104130756690400455088707304445413705351328929165333234368784089915392964323220700576801790706410314713112989059490000*z4*z10^2+760186206226034667562233288815026351734401621434667392158833370762528830736156300105396822649000898353229670000*z1*z2-649365617964323824461662049076628442160133182006603515630747116556327994834325808989490613599244184435679741784*z2*z3+1105866738093382482318892799922417341827767334956170125726635973219507643040059090104499232414168891697155833192*z2*z4-421450901332047085345374261292171119139383927680775702581642123141225130017474749443226369101383377565893104196*z1*z5-332226278087969562924851454354256885242596496762072701739183638200379734179026906969096825079810018125367472096*z3*z5-154380971914361027512149399325318871507517465317148787970378864526308951954910595517369972066043312892280293650*z4*z5-650292368304946385690509104163659190947589908002384704305134560285840914839178765595026760821860746111074564796*z1*z6+617707310452982779547359898480700017714390125673133772579897309765563678061328535762464395233511475176110515596*z3*z6-850451389604067643367477365632773991134212541041064774877691417766686321550360901927067442463817870657209886396*z4*z6-45317412601513042088475096210725056105729170556146586105639567194676816529673051952052637270299304430449480000*z1*z9+9290897225483578694485779153084510355131520577531164254603712901569830739820184554461990230100966474416195378600*z3*z9-9328264837531609067164890536931585347774446105440671172161997889976289259756213262795778980956918340170145005800*z4*z9-592556061296382915268933338056404416872962133033291895540453947802674368935283810290681530333856162368893339673550*z1*z10+5195317951129874954943475051378536709620381626908276539492926631376353558903275311261932160933900856455812912652350*z3*z10-2350964487818831310824434764289561063283076895341969242222242248777852822883132198274701699758594999075904916688600*z4*z10-1217703292929928713709552346568942277268964990247332917106656837611457518099349816898931249747320631899228723225*z1+11061559056988499174180751234842858653467933687704947585291615293460872109425274018848973085483249755681349359241*z3-5703988014463328474984586787187153605884395847770183238975766430559795947463949007891497054664700738500150745808*z4, 124507531701999295272810808122782430099906419200389407046928714171931742895894127230998454459885732822522758936556891028391375864134156058816314891654510549876250280663890486031296000*z1*z3*z10+5868712673828766773092704677334269354988281262111618802269717496133024986936392419936212218054257056190042162658370792036542800317407273284243540108112461402835403497371700422850263648400*z5*z10^2+9130547861707616345649364515359693351301388129770058126090109303013888689829568445608143755475923606170775767984442339973249827670388603190896084592408584521752411132285595860448752989650*z6*z10^2-28185878869354771796868296829619552376451393744195255849010152209026178310901512919078501499723211014676066405333016017775020982063678421625342059310321813667034250442250145705497590515000*z9*z10^2+22266244087100978995524490023202737747535852786870790638101232738050749006699395987698789805099990909642708211865012873159121594382456608846456664162039909017241685474370984960607788970203125*z10^3+5664499636113236699937541864289369510661464277691528440221377653621925560427676081162861111678682147906311252340113283949263258339946692628023924003068888470428877233918024120734256*z2^2+1106733615128882624647207183313621600888057059559016951528255237083837714630170019831097372976762069533535634991616809141256674347859164967256132370262315998900002494790137653611520*z1*z3-553366807564441312323603591656810800444028529779508475764127618541918857315085009915548686488381034766767817495808404570628337173929582483628066185131157999450001247395068826805760*z1*z4-3430718773322967419348458708140377652304831882097899664464367047917226893223027869212660006523204944460868469898192488642743188596846028617530852976076363098650119083272937734913550*z4^2-11727234009063097758494822324075953181950835289095210592272236295343038136297972559254891752366445259627184966000253523539322559792919223944527562388004319730883326096887578359804296*z2*z5-4241880247845115702789684314826062422663807393079651569515422828348940713517307714396963610691438884513378326351481001527143987913319834354892670015053206712908211257158384002213830*z5^2+14864868277494472941525354755098149314364400582110413192125056731045642308037585850271470464194607642539324796722476007191371248417538053838862891024744542870665759190504755052771328*z2*z6+6166686386286069637017682530297304408886750976032205008488373691672973941712556058146918583493910736969292308173856689441129009226406107559936180099128301131129015158385226103344608*z5*z6+4795934922817910904411341765604889526131656749550881303650872268412102127987403637914305980044504534482624788647265411859694416378378011823588572580069901636535261513704980610502542*z6^2+32833401210394750016495329519169503203167767058616175549820016586462980091690567089600101004651218150241816411822379931315878461860233510404251105290569562512757359320489937503352576*z2*z9+28815026937807660781918174634670735440668166353466987785012648749313384612069914526639321287638999796349507874637220766259494211417195565573552242967682967802386541232188693160505216*z5*z9+58702641925854381161402512636317887169235999239025057042727773498194320337006233577039492289714772490604993743357125664123142013120321649650267523221021664711999236240704538915848064*z6*z9+955075590752665802741043747959988884897144907541756911665646257075265743966165236185754454775066947568384337609745454531390194684178360773744437887620107010196306288495083520000*z9^2-172787786162053200987095361017533561955304746094701183747104289346341201395237018996580804736247186425579929579713159123621299233229812900391006934761306581087441549454604053280106656256*z2*z10+34874096305932132750515378018203652127837374062474211725372768059770681817828376563842690347271979335618145459201508525403925301706331628338612305371746303010060899175253768007604482628*z5*z10+131323621794425888803527497796122596551735633382401043029006210212903526388796448950816397087871176333092875626215851238890504922629468597210495874688173800194934753314207855440272346672*z6*z10-127037659704712214138778429308517556535403149177157565973941070361716252442351547822398999445637399819009086204915056889267082093549084276336397848753904090134030308276271962082749042800*z9*z10+218676446448233780215936223275699998298511181258624573986003118682889602879308585581041603282638090577270990858614350242537985738368221064960302145446992492745392834196038158049967404805000*z10^2-749320499873837284714941784941054625496134476941918495589712118945680806730666200138061306037788508560706142308089962013028704592574767639793680627017050421681866282411445879882219040*z2+45423357994433424029101148368616021374633739565972847726900688504344693106386882354366002035030142708468486997116334467790550641576439836361136970921337822086312597724665045601967788*z5+393102974111618819351022753174889340682846240394072699934736711719973912188972742019650860526037043901567716125289469224195109211155614405701792907755921573903078472291575320652583630*z6+33245276567232444158183815251885481000424428538744523521671770301200505468610664346017269465895792541370448100525499142856214461512474015735308208483953751944355318935385918365003848*z9+246006387535544666226625137934402354888399238864842332682678775708421670075150742770603893253876281035839526876499105588133356325490809892341211597982207867090307471101545775086588724805*z10-1991933812559643653015208498003506476838280921765056442933809374108872200266665592096899104763139044364031058724512701643923815758623726349799683097778810872442816612258002235530595068, 17292712736388791010112612239275337513875891555609639867628988079434964291096406559860896452761907336461494296744012642832135536685299452613377068285348687482812538981095900837680*z2^2*z10+6573865143378179750920971744367827112076283236687273257282546629351773548703702777196186558324464497546425853520418284047183616927816792942296994759805970014829574674706426609403600*z5*z10^2+13578575153291639165700071835936722714825914958586098384616780666290662809619525742529276509966786771416149218423795263083746784164898730737125646223822372002546392779574763977953350*z6*z10^2+33143648718323020366926585235825560167694468828842833777368151513365776737726784919317434066685881557457895292441600549494820191927500948835340984371279118588034619338827651560715000*z9*z10^2+30379318290475523348951452539378322162433873021306378501468648374597096041495718435311265117241377908123625781684995243834199967547204577989626739455558098439811042003637395617934265625*z10^3+78989420447812171305545511100183006034281218172758740650005651479253318657848686594977421945144888441166101198829926485011959403765580994835314205150912593362683177376217250304*z2^2-8780209067424958361710937835150770360890541642001962793031863652326188255536437499607898518683796878197394650661518634460017344870476655384966110946327084808583068203126369310*z4^2-18623051945281873585422013153765942593777040155446191604187971897432721406137000326611603007556301239699825729852360299826101099539643552972941629431781021100186583557834314264*z2*z5-9225539539506448233677963644402790322163169006962736014486142848454087648745810562174743896912376816825610054909193780436321595244268598523909840607158908071191591720024715430*z5^2+24555058937235505861785813636278525090278414428699006010096216636181382314600352977124137517803381677705735726121843323240825052894530459651873851795509690716607099503506711552*z2*z6+9948397551583281737613645628332751917279352980019905702351549982940328495233018375695406110688272731474423214736438441555445166208129205301756298403594909479257975164568115232*z5*z6+10804999930372446848930310757886630251282303716722466565389539287494736741586284653871199168042408642447603525279643437350197021333209794614167210274908696216453809642902743198*z6^2+56847150853534099155311689086566637835157448024664333276251827714761452154319757115590237356456444131061185061028961357326112639588976693542558743820514321139800930260402434304*z2*z9+49017807842460337283240905724209318055501279581530963183551556200696084129920938839629987102270142197665432849378223273271309588870494966449009261949130181487590112476853421184*z5*z9+100363513485260513887107477658676025487910860684299041081376192680577192854479708403956450891863283674093706104327662225773497342376193460029554638192168042779602829857236989056*z6*z9+1633449773482052730429311842745746441342871156309284388535955010626942832948115083756841431018008489727326927345827496899880422972784498708074549972727647193051565998080000*z9^2-289662065225061805803994883813671059204781051792507010355728241678189029721612977198978164669785289981356233418682505466163610984542005406939968848984856028616109602500885808659264*z2*z10+35550220381562020830915984521898539851421177349875780342510983617238663191311720272988313327606831510368902677303582608521041031182610792394711682155920749368456524446532430873012*z5*z10+207231146931616179686341261956930011465105658879075064652439791830725250809044738737357836925280039386341176221373468011878237144665020260442831832572729624689289164362834510507208*z6*z10+522648583152841022773242588106218591037116574501618358808825044885769697198317717615343698972433925757694424905523216193431537973697643255059945300924245518991604927488907214818800*z9*z10+208300468232236896321778445543217386811750362239565347012686248167512069707133343491596064214909293152725264452053999538772626979589597760228100904996709209211930615524126449038591000*z10^2-1284106089726997445401797584455366509453272693677129932445198293195473948369374956610247230382700468743817795235961941707642475888329148310022112812211938080034481371797507466080*z2+38042453469152055267552232121615583651489718623113688898243535202202677425303289320005132182976452030994289100092518402926879113159104522356190225366719004843103484530537502412*z5+644311145776821350069646140508855434648816381522803078464996937277963950113776404678996554203693400635391315848549177345856023670922528487676140408499206350806032608578268838130*z6+1738509075102576641518457363970748864060547633172070464799582016770169905264227410396642570555681379260063557196780261187757339807807329411184293653090515164396211664644014691192*z9-879580898935280419865582688546157088246645490876882321292408239315652997466514964766355464404538695867658969264393749406750227019237595945002631631178973730179175431332509882907575*z10-7259525427702581631845237288365470108440923096193412106380862425170523778648508931717149789111394335090228977338603901635409280933543957798699836044782267896708431807998191735572, 8392571212134689534488862312286537519991213804102617190069697339555910568015411166244960880106642264928204543184800*z1*z2*z10+8894543670513477338135299452849200795044933473786765435520936289172514201450811469923846572506308107688598081635925*z4*z5*z10+92394433243591168190838435831968457612552165750890739417704272384442867949220555909486816130898282220960590414000*z1*z6*z10+1320484625133039409915570244808248575517099517771606100384493076250364343156893686733642429574766952919430374052800*z3*z6*z10+5525396178460006651474871934533316750745017614302905708044662960052513208484971279603420326927085962463375645456750*z4*z6*z10-39056581466104192169423663688840261383197712098564890130380670912003409952252319262604664141199906390420254124640000*z1*z9*z10+92885639265009924187311988704146668340914106105575194599034801121415195725470602669275724698240639860604781271813600*z3*z9*z10-54357543388106402613531640405599573323258527571018627720932363759278487667226456560532835807218393265811657869260000*z4*z9*z10-236740731862839659031033008816690660235130773176292426812352349921637699631184405236877482550424135007371566243828125*z1*z10^2-7107803601129060251768504465670775911780703687742809295960726256685594952837212123857398984213258136359408664374531250*z3*z10^2+11417047914852867823216115584588117233910644936412662518309478914983443222232932174245563975089806384767361575831644375*z4*z10^2+53426008008534933893814009052683681598521941624710192122398310615508321565125579141881913716023069991801809839800*z1*z2+97855072334559303190889619969069108663526759836908888166147611479597414364905329382407283230713945191741329449228*z2*z3-117010032516750730173341523000192865111881480002838568958877428694330124063828199188700239643256626607252827127364*z2*z4+22440938120976038002445132221734942763859316871458309381467929328901407781350988274034184057774692018656159989332*z1*z5+23903821040733440206646890303195821805249095742436114739358213571841784547425791189011280627914059482444994912382*z3*z5-6656440126358212574880076665483709597105380201693412668858221550161868048307827324546672057441744141122494292925*z4*z5+19617597598212000108429197937354334426589840000211327753817599141314177066302318285237581030723032822773039773182*z1*z6-14451849021314849300451092518906843008453432082878135871498468883464013900798869957936420459556672660698191893582*z3*z6+26594450985151800858838543499949645434175832686034410105680238313008039131663921639078390677779461902596318155582*z4*z6-181246718028313337592552867553674925144435833099032774764297187412734879384011582111076875215995294274237625209600*z1*z9+424300403835159983212431382185234794824525104450820212610633183027708809051272771103965998057959399185470606879200*z3*z9-245412176328065304993840794774777085456219982619081609716666936986876543794536686630800302374530443973056179045600*z4*z9-13307547347743585409228155114537511333425775234833529574776882804841785825216369168123499498347888521056615598687050*z1*z10-47178837502144348894825073044168416101701357066650342360195072892436447321163270875346459335090358357776687298644100*z3*z10+99379594845442739845163072830706234799524642504868822019867763772572535104002461155215829016626793167648724057598050*z4*z10-58494924791863244365578989004181202952632746822208569522334885714215832645829483892388523641095227564149139428925*z1+10222006118510022378624529599328310189749322692580264485517811678251027223353832657139643539504442772521436392378*z3+142662867126816398084120255743664155159000010469409831678631273002008472427913819971228349244648661589788887512911*z4, 108611847852083117096868850491981832329208527857568187822268597132653912690105003472562827303406785141374795800884322943182395475146726263574838438201353369166062487113502699325806485792235227149657983418368000000*z9^3+4097874627059176776220270798210613067330379176746265021250360640377457682781802077681311404881008492583213088146070366574737649366045978792672022135708826258325644426982274436515472560940483809551225720212243187060748004659200*z5*z10^2+7834546180784368106609274229819052907910554939542837634085769733498662790550982673955029664181550536302539377648368168595766145912875206940124599581810397018151563788504874004293059166897521730784878813379951609391068263228150*z6*z10^2-211359720174956123101150699988760509551691446280497070611830456470191832735151798666435262575008919071445178388425918322539041880547381251206405110114268382722906517022274221008425002665103565414376747379556126339153251626125000*z9*z10^2+8457196120976253330692915097388297758422343303618233187994015138276937703074272597343747213184143973903081369053302772574171954527542989617551208921330305054770243315168176740178752078676184581553264350596775649198789432715659375*z10^3+2057436553837970435077634256337517637992779830321021994952308813934698572069662352880097154051067584213300768707574990530114688379554725470290283682807805872996491985257075733435171350161344666837163735812124731424743088*z2^2-8300720197807070861208704896654169101667402292966832284636291152202341368082542274122073053036503238300282505934411530216111702545784249887124752704995484979934499743161761098904629754015901485775174465801962758039919274*z4^2-12533086729455041882203720786941738749952315261222413060515880933070266207856659756428740441813190207313315432645612687834629888662625814541293061189504905482083531013009842370771596050893058962115052422690123377772021176*z2*z5-8575792281847001242360527415619218582582590030411308594816604437037578307065258489102551468291466831646361503455164440971554612842862465152620003489460103901074291369683704169288316728074939705621515196431099345479845202*z5^2+16770167230395953080828845734788105432121723886261329894706492346387248038590826423079923626832105687677994679567708855086948593496427436875546696945077739289242102876738421954198520833500024750862482183630451495604698112*z2*z6+6629120535146447758604061824720516772282764150632268711476065128046775411148134938498595859434088159824688223686517250869642441294231266001489576378805091411334038964808432325505834396877865262001391359423535313772477728*z5*z6+9569943774271444675734540937243325738522059104669824666479023717896826669798726132608169544792264756460571228851553477805462218741725571719008029829846501616941048413332987191919545903385238602842944766083190322227376938*z6^2+258649077464410893416308635611378786533707009886913829744019748698615035925952154326378272915946433464928209808479285745397780248545047782667236325815063128282271597398557332466614210795264839436940744828944027389818871552*z2*z9+64447358580098578100186561830701397817614824926945264948980455220326639626086940049640222637372242290714973148387962776268429016384454195743929301964518432314854590830881151414518324454560136437969680751565897732424523648*z5*z9-52284653737080529070665287297061262273429608738649728448658884396400714082872516894067083345275639001309886610159346421463148962931661203736378111258141398977174174337310805258364304511874727556889682862705262613153988736*z6*z9+3846329366953900422011213604719331028576239428737042545461246503933769027291840469975835150093446090968321823153266332071810359130537671081654556497432242841197233789100133448781636734349703787583006590561921515520000*z9^2-178186882856743582007636707536430010770135515488041779760278754212838384969412666200151819751666843005781317958597165059864545200832884913746758269307113345049362257712808359612546431392630814721170595692863290634675850384672*z2*z10+19856207996343429329895107708434025853150887859352620155036529354100417383125847442921260046078018784182733762148599819930639033240894060049910146204462094202134405230250645389295068264349289624470531919952474345662218287228*z5*z10+123802309373060841691976155961745139560779778945027499719542962287349291970378239388690281794794874342253876929217882048012481706167063338076280682711562734720688130246402406415156126225358650271951759225871142659546821866120*z6*z10-1653002087301149284743595269859799909383734959955441408242199908267403735830466626510421993480629957836568803762890804076070201320122099964902565566032306075599159421054042371191955923392399657505318259666507109197746285862800*z9*z10-70151120772979483985254704927607767496733235574715301991191435820475803319606014376600114699298278655770817203294968322480816059591925889123375640379258691541664577336209330214366669818394485008869274572850669766979161576095050*z10^2-774686906990760069180548401967557984430788715561757557743591581450853060741136516176986375522400239286007617670049368579740759118968386672629322938249433342371010659532516830807798386946665848853788834806553353837247080736*z2+14111922575506950490347146791720782969834557622980083999476685973187175714356501448647186268464206426791540499135757325523841538444289471043161132440171858110849150192568047805684932010347628700695569480730518249406062916*z5+383248316135356131033522149372491490938581510197101984381425979273331224763180312667015468038577459333038353088605006451827733180281860798733350344673486175591941551909296283270601119501547927707632600181617472319946614194*z6-3082376646120733584941628474154156019589018663737118505567833135327874073439579414473994925631866837305832364535229595746089140796107728458741839592324063170365239738006817702637618864179293042391457163006362966847469168200*z9-1983255128357648626855640786003370755910154856609766062933449337976626357500079523912466970226973472209344258272505409276269262265977687436092972472500605651546907766594946066673111041779993486098683214672845181244861263185701*z10-8500019000031912098541438630918496039854129329879239011007613096967663753231755588564747413255986889704667422700095527958168769932496488152737279970725737448690047045098251438625250263786498732175487499939237115236038750742, 15936964057855909794919783439716151052788021657649844102006875414007263090674448285567802170865373801282913143879282051634096110609171975528488306131777350384160035924977982212005888000*z6*z9^2-3057357285085927770605619144898166074473378156579358395629951376503169540728275259725055764652783804111977279558776155191486461791624367354258510655601387201731891770271697566409649015059494800*z5*z10^2-5843549365697688331629894976606251876552773294817014190742764273080020403643200828238851129864850551704786117519886448464547169878551987433022053892969333919783823730699245519795848551492174050*z6*z10^2+158130634157864204492885508041890762769207305584171928781845002318088030523232335626858683405268247993514685668795533642812049818048833311925658621484255402559505818230208191991143675511184680000*z9*z10^2-6270359903193856653679697736835196119580121633929288902534724321913627793111013303460970454661092371506462920347362898691706611440357017289059742933724843218232838358344917646380651699959762640625*z10^3-1538972682677618153374444790558432525361412895211312300001944284322689936163883906042634243280784382613460762294891265739765273669091612441812726452789101860491919497626677983479524141072*z2^2+6206222337965012993528703188635988052112079982071430736751963710795959514763781229313833360178175438723176380176577936083067535604378013670279118319390951555904718357795204637462876780550*z4^2+9356195071919619654868296319626253774286833293107167857857963789555251470646957410611298639612816207599225156854785401526496023891210596888525366560746539694352044839843708173630462355432*z2*z5+6411459054164812563282617584195071232612214134572811794937531749753607708222775484283388758641354970987406943829877037876580341196488072611171091198081587955949885110568719405446649671070*z5^2-12522910003111654807040252062789555638642250151932995044514225664105854415646375680808589342216607217640351695182155687233791405973674982001130384690592313542427799218144058176092773405696*z2*z6-4949725244203548647151272812652710335910285293950932782139275888364222302822759313741618181764224748168726327193786884735787554299607051117110906500174551625917414397562928301683497097056*z5*z6-7153423515077086988867000731827715060048856470844834086356082052756218360843560560349828393542826424438990902546211712633107256869630692383921282025084362169614137992716705520805991174534*z6^2-195912490837723727669455592527041011525088877309536109131415770430882639748263255725974756201019550799966434983028963847969006713250791944605941047337299083554651280953303301950506181810432*z2*z9-48206486856272596891591770640426715326704999904725335961783648897927721755290085684458103940170214064665842404730397944582147668813659437786223817545896385089949404561885696687609135421952*z5*z9+40057780242555194485635334468559280486787573936195719757881239205643631879097254738883784784983369576366425993510523636415308753123968152309162268834834441352630400479591291742374272975552*z6*z9-1531748658920302953372907276553254905112331672313649282188705932625732217900382604244697660091482069182600633710534506266514631437069579604283329757119769076359198180200705990131712000*z9^2+132923504013947238090381825625658138163904463634045059946836811580728621279693169240075049450649623487909534874991054611617886593474233557370908039866628083469957816995219590651413079266496992*z2*z10-14815897943343414660217710628141154780718889879418644773430122756768501041461806656907602053855822243105418806481939906308277892869727376722055117008003411421527279707371213109562792722248596*z5*z10-92349022900130526768485170898037391587354604780069688129500582878138667062505925627924207287274381994467286595346822539960818498238988863308568263599237849212102423237090490250544142322110104*z6*z10+1236853327467960780692202986645558984445033546147470383676130324744603185291066403565690777396615312779360493259458534021175389945417609672772659559167127223249812261247379918448855687123433600*z9*z10+53125470545255623044286749916477899652272565734786927872425033372512392642296604052882850032647715924712352963578875146973816006347513005092769944483818332457992867295249270793697195389250478250*z10^2+577864223671451695393349646426605771279714042446215445872339756755983626785205728545840274746641355601788513679327009217088618156397591927071567684111931399262957017884370389398560864631520*z2-10536727790234370650635937786411647331257931101335714389047020480402098506240745897289624028935112938704348156934530191397462264916323451586112522406367833723727497490513116158224072878556*z5-285872707763628283273591633797136363559392397017480533472114618075350355531881653159922329353943127033432869536603519552198945742824521216352607231920819423167749238123756415600775343029590*z6+2306098871634974770006728347760274943660282883283206563228182510244317058788138575306206232057665842734864868069245907681245277169865470932129455628779505004004229515721626464022848859302464*z9+1485613842317565831165169901385583046550078276442547346978591799472620930236739030333173717980770579238057791637404323905871661127290556444596532269381190832738541600740425639550103095262446915*z10+6358981719599608475232289968556310100988013766361107530312536723282062092949108328017164139892962199288217672958036402599359615717801001246691072309538798558103628032714520527752410896744206, 31873928115711819589839566879432302105576043315299688204013750828014526181348896571135604341730747602565826287758564103268192221218343951056976612263554700768320071849955964424011776000*z5*z9^2-31164476051015089156237862817963847928797836621516469406298188812403511585836606832445744695408587283038445491998279421766738805799778308335787914925878865669845694200299821150713399737553666800*z5*z10^2-59549030011576713720013399540530708153068407114861176225411628476102283445740299572435419311026813545490971088754424547491328945577183659926625159673761780529534186813290405008123758035169248550*z6*z10^2+1596851415530020695374250635558678351432143947139217940479998914941763855332710776196131980132229892661515255256584582869213554120176842018319708419613454138349676576464672645308322293550030255000*z9*z10^2-64695882348595686308314056307523284837498760057353701886076166843431150816367288733020382005867054334028600993708168349523426457094532070590259168831572165843934945361684509488684459561859714671875*z10^3-16370100684716765662511280469371332391010759613403174862711789088236814577841645029278133540510160192883904349227122618006569560305932862192775258981633501852533441887045839531185976190512*z2^2+62968801443499697948825149154934432513750021898663494102830281600370657154486513955029774535587121559011252492104299514590997517090122556662900841065767545128671083941607331014717753553650*z4^2+94953156358611223171052398923528860740255550142488459561521092522592694616594439104017444751338989778856891534404808228966332625891103763924427944070344297597351597455064074358544553911992*z2*z5+65060708902030674030825440792864680104638940306757551491972990230694083341774291506801836932875384366446864240707059050987607093586474298644282570787383549285351260694177923484170670752570*z5^2-127058704198262560404116120563604754865550466516791278275480502642025495710494640387559407930520837438355986364003872354195554969891307460855678889577636988670309431432159136384531507772416*z2*z6-50229471103431388560174221841112978767818474294989352059567907908353662152974321193218440716424490634005491803023725511465257454071350637177503597764732820685347697613159123560690033626656*z5*z6-72608549325300085707220746787050661540009324567139137163522208504023093275998957461261699555233468887719413994277390787074693475634106847672773370236398481006586614580961606222688190652274*z6^2-1919029239947759858672753408538383172709793895074383770938289199994074330680012571410191175173918080612684516799862334783017180089144243927268231276734601087545846146434430797859492319973632*z2*z9-488898428833718185476337086143802265977794121735164921634025351738055150030921395725858316764198982036723375417785626975551361225310403457563073276699177428182556524376666534383260204457472*z5*z9+382907486015552396856371067960068342599912968661373297336766320986918411696683303572874584497784992036327985239937396411020303771140223203988366419001609909891750432586403078652756158465152*z6*z9+10305648247443861393754047132407598849286054796242595171197139668449093238264245314965084098859459762299955894932183489689861784016493779163970943858290618437472906996161732338728960000*z9^2+1354003864728684222431979246262535641014902361774390478840010419750377070455203747317748065417319506391692074512179626171786155194214460311167163137388550686230344559880785547575533929729023392*z2*z10-151092364430083435802311821156557074046612573708351081098901458675669064819364177928037770817812764465995331783298021278517663748021719866996144988032364775761427325045565423367716513503191996*z5*z10-940828609636604818165511256015403219575126203331503920229325822156303114862941234878649152205613399459516052520738320173085700498521613651326363544648269879296983078822739899655936359577256904*z6*z10+12478590052351288674260708243136092214105051020436333822979486934729528058584040803688930852867643553536132500506096484915560562615960527327939102171843875553429326670859228300850438113664695600*z9*z10+524968508284625294921949655694189581793557142450152090947566778711287525574046301356222776863148741409905454445676116540585077135349047814970043544607649028564243413877916142977221994397278900750*z10^2+5885508699648215785297220520247692177536105498505666623716523133065887391094270821437411272859666334326151983481059483189860236114868882672808487750201793689263527648027087333735041962734240*z2-107980779463361140740589522881311715722034619791098806211340564324981526092813034629482134709306060864330794977618156936213455318070050326043669557293058154970232910407455772588386889545556*z5-2912163394838478146296655495408265918298569280909789579869715507519246082362760722653299320514679975989173999411817045079331929235427105812185267546798280511196828972609455871067531385383810*z6+23241906157722587311867497951516427620224540811505955560920553480233207295184243215680310464247309422119542356727482296589995630298719970457715689322678572961652770882400427632328333787850264*z9+15013084330863946622620741129521727415733481863908757857874423341924614529352879151043973733942810947833323975505090013219550845069053191870398978176063907751398668445470729571264261265181463865*z10+64433264122685270419482007758319952749940176752575866798114185891902061343489714326323357532369246375762097972162324006900666841854075908682792190361933903994081167464627969614328397607577146, 13727071192796995149291548386326106088946093477087310314001020704260344253370935673368564271596443505257905584168697607799315125892064182272000000*z4*z9^2-110205073567184789510022612571704968708084924004444234445145331148051718455073133474739622193621706656194248704165200281327622594048124348097100914958148225*z4*z5*z10+9363610952507001301805156525557181228642193861882813849058105133737783995162780863122953706603742464883067255649399534599430242893879310251237684628477600*z1*z6*z10+12669776876099128556094546928023473509929185154656349972412692933919834863726827773289727418135176337071816238139968695929156264365096926631467491079125100*z3*z6*z10-83759671462234637011991426019411648154770003784671607128513445020658071586293528314041535301738978141062492525480038471943962571454983408866563988008016650*z4*z6*z10-348618750387228396568547102526635550178765386051010416193820336737863071652263347726271565644498841301726540311702267751169849697484484717320558962960240000*z1*z9*z10+1418647880288566509868711488413957747684911671397406964818746959553723251715588291407546354148804062393628092894375766256204283344573290091760073252128874800*z3*z9*z10-1037544143398890885070178009349686159044311503637204000900532483225490405139735889979165187902406269290579884066424036098040095238816612851853458798376710000*z4*z9*z10-32900669879861078266270651232478267032405333728590351602836400947787315348264663869308632336390254962682736265746018692170856815556534071257484246838844765625*z1*z10^2+33113382437698120133460296058976991288135659742207416984620735821999339157604774864020065800057783301146884334285981625835070367809906966142549002413759375000*z3*z10^2+85441930233541944280388336874291542109872633182858302577518221117900486798431684737752848254307553362881424000142679519755807394715650672781789300919044423125*z4*z10^2+286243887899530640824715718509687387497192272404201519917363430342086761657097016697440842363049751285192446396734342227192257992783733766806896046023800*z1*z2-1032491890801335709285173948191257902374037338587458766769352403030460095642173572712438424107014576479231004896655123738956822322807774636715116556243268*z2*z3+707407723292118979799674778827618061640256267009311009520115705005639408582504061149385092980348532644639636161580148288359678966991580435387224113495884*z2*z4-210606169790562145618961302261200488068982439331121709290008657212414441799067721997689768740207509781035207206268656574102169702034533050399407826308142*z1*z5-182411225332808369511397595962020179155949942954705071354204552295121532456559848457465101909208684693930602190145381111658864525978974199074529330376392*z3*z5-93706990570645890723950674882915447669717146449330891562380180940434677883320602044653063505430951925211238347513787462563634762589541911119073843485675*z4*z5-281550745978469477324435652648315381555028163593105461395737017604656076360739298431881961276846643882470861369407669819329040374351640860238805541942442*z1*z6+430181235930100747291171107658201288141267881966738647865319055228401013734951171089304731768073803125559611157959561790041791622196316853021845648232842*z3*z6-411429687547446837684097273407445500956278053583080553430596504014053902189294714382586935787454690344524013153714933709460212453553242044354785978761642*z4*z6-1307894671650646738536622085778911083431190559029898462887935467984587625262505353159521173788362431833724923414282582094227708469122185056411796360160000*z1*z9+6104133265054965359585262169012438068122168294846087407488133380737807051783998312149330967579364751940667237762261193328012356682830654983407347299362800*z3*z9-4651145821085500368122318397349864821257650178629528990018927006393187102505019675450014269563043319413290489542910392167243337535788752310930408110746800*z4*z9-351693514641328253470716164298839153755455689663189198433558644450288158832381261523682741780442858220292277932043600469920119382615267058126234534488656650*z1*z10+597868737620433596389711837264584401251568619648895930693277538292558231921096851488507167257101389366023126905208098192894118037574293097231798687461779900*z3*z10+327602762568430409152724611927135721728008758918836483515540077573871799135983865285886570953430223926194435480993014673297964394750144837300703004381162850*z4*z10-783851102834436288936384336769050203527540310624510265963731727936560253514350020026680313284597710838919121046003033395294300874574600630050996668412225*z1+778147786182530586969423504215776871564479181449091808227380756574896496508958510045714006239005681517635992131569889413129225192038765199169404438920832*z3+909550397123935640282010374630472108339388239665308073440350451394986635531517145793900570766408282275770875154579616879443825011709098095254756768171009*z4, 20336401767106659480431923535297934946586805151240459724445956598904213708697682479064539661624360748530230495064737196739726112432687677440000*z3*z9^2-163367201195940760039530197235122345014364585563724879550790697158832761986112621330709229379173766155918316697840365375350824359755100527272711976291675*z4*z5*z10+13879056865365535392873455983195408333290114670856739646183791154680819917830232679960047412999971625614869548621516719568113998382779255999694206015200*z1*z6*z10+18780280072011852962745373914310943088065057066752146485386636031072057443136748709315996122419098055601092282118756056395989990243518689901211314931300*z3*z6*z10-124162876604531577348237738323841638068621029459080765908440029916954819206428331450317832082437110136126624812549412565218962444073114289056154086983950*z4*z6*z10-516786824366608190734787775814008628679969180237454654969366562974325577972826216245436928047817460563303560068811143623620464359184336892113635730640000*z1*z9*z10+2103077998524322443612480454259800976639024331583092617560327643758668177548734077448901866541829205888615638211854073135330316811084830077467657637366800*z3*z9*z10-1538130564215097592347781927536157656177009310297822271859636095587381494772640533125030480070225130350124438108460963180551957928642230491124454949410000*z4*z9*z10-48777325449187619896215735476112489030193310110554415666198163482360183071388448150902767468826293735554416120929333313526596073820764831248468425488671875*z1*z10^2+49087991907417408323776169838661196916992326218042576386769231108966002415826897498154453821921866201029317629733783984953528607621782293181728463028125000*z3*z10^2+126663812272994679428677466080691313617783700960765326792268056282778876693180519285206861586697216723737124603220759050961682878997184298490110507822184375*z4*z10^2+424328388778574271686632373463153507948793729121061633054260067189518873555476802532119520324254779214748425221620720023573211318404251725708121305000*z1*z2-1530556047578502541392635019209270416298631893188478400177732260260814213181163237526537558205829368201435829131968620346755211934933048759863753745964*z2*z3+1048651608105064696646146052637633795979697824873231866880089564338689054377751580281897839397529054044791671024620525494370487506805608269957940668932*z2*z4-312199225974906574786114322188919729862045332201990048751087857525319358386464605981731867012223534240842115954874787835897436855334911466904117586266*z1*z5-270402999292248317331087792851061365512022072351073101417304327617695526695389251257388100955825051588363507033076795305489825025372385174829468763416*z3*z5-138914492858442692593107116647290035101219054490579097040624410979619174257216571619939035731409085551271207640917609595203903474579269841482098857225*z4*z5-417378981694885135903960477190353587535920731120041847579927443996109135324674695433606001310386348660154667098419776948682839048289839387961457942766*z1*z6+637689903781737774088179941629099973745407084262938987805660804498901119794703986500193743135665822796038574073729199435985261969288706312422995431566*z3*z6-609886924250031754421503566833802420930721272792581011650074328934684598727882047438201336884383729950881089724354453035741356178653637452168274755566*z4*z6-1938818010364103446806682423267818610263637435606409033453650666774590388433468713609146544662725502442593859091899989747615593859354465275621601542400*z1*z9+9049093678378881429065045442318617060636176084302962487556535790478146101616217826365845466164595532358650780237464980318506787554330434555834879890000*z3*z9-6895168443833728355967477857978053120466140608924939041791394771426312443750732861349800555378669179793696080492302850001775952892980742909224891296400*z4*z9-521391630199376219236557930819934852894043511208751569330970916870042477818075441687649041822333310992594093995936392808318477894386936579742265061569550*z1*z10+886288746289033166053065429478963107338951447616164391924352987306004055582834696339670236459062885503828582155627689966889024605012408392242404698502100*z3*z10+485675091519565587787708374215262183505096715127869287557127057694650078375070650859154408328128955526377944282215641076293893260273562644507017382241750*z4*z10-1162049190625366410688846914238876071180379470208904989915042787657819151977940852847847857884375141050036277742956353729671316106351128331698856397275*z1+1153563882498912113043157467869883290190049440918301724434332033961618737058073836792977281679056483905247629628229888605491153407045023528267751273536*z3+1348366369050641582105607940260762964267346410629731642300784972925163574452870022700477124586855054968247226015777942031755054665030188650209681615707*z4, 127495712462847278359358267517729208422304173261198752816055003312058104725395586284542417366922990410263305151034256413072768884873375804227906449054218803073280287399823857696047104000*z2*z9^2+27097285737476634142558130980625495061115047421452157118068258136192100471013130456591141726585885014623949012734903240790098211940693293701683318201831172387924135376093518842922961304764557600*z5*z10^2+51614218489451288423172370949621882036637372657673849300218068024388599582100201294170538659846528739474765403554735757389179579426815413810595851362727905068502463857308321080732261203974897350*z6*z10^2-1356538052193950860026559014955749435966026648199429413530199776927309592269770749585993361198970393583190848166084336343540551773677810443234748154737235808153659015594956555160974207735085085000*z9*z10^2+56929900767385543713126674887305675746275196802676615385094948462223931454649925781691906577176648567275022995371111539117096964482036942145956196122314557502916146461114374695685626248399984109375*z10^3+17085848746235490634256102044528697231532803102512044987279048006281596966980197263906628747017770608119100539879850625640950787550017683209649627657556864441271575808220155457553424322864*z2^2-54395005491784968455821295867123728665896271741588826626741609023451809799736597990797150875205911956719609956274607046725787856382571065019009433677602145913412232702934449708271737702250*z4^2-81272808937559333838511474212486216821061648530047622371785821952972286061998516684546831169746044229793021004544729339940704182810118247779822977494525198873530454172500238542480804771704*z2*z5-56213673878023147787427526881357616434308416428304168738636454052408646674161702826230783394381828791133779963745053502786411357723230976629249233687210215041365296024936162840407108836370*z5^2+108839606571196028643012544204345927476510944392306340553386857979266112788298868389134985195200396771060544722245300734880154533440641521451215838716159779111588733937838685677445415181312*z2*z6+43033483795548682690798685259061062548792297305876140929162249464585925738792749658742510639563562385432980092032043068272759372527826087251289800796928212574259458488169018938729299368992*z5*z6+62732068187028808017533796117482297803795980415108714563275590852344257556822317510643318975095732309959262282806580559684237549283618395936502941113752319617318188918020399586784957209578*z6^2+1539304632530632607542209618680299379476332008313174456761938968852978091697666671964139507651782368593385095736427562082162306152087760210456569458575449740591042812927531267248051593620224*z2*z9+422732784454672073235081446550153602632457321457684974829061077578458563149580930983043010206183503410870718227710183225272656335313599769644376902527102123189303463258556833032651188911744*z5*z9-296171060219721794549452241696571116156310651200332485510597504669430892627242869806949446292984539539918828784962817703166367120682696271886876280400304067163655388298172075475839727073664*z6*z9+13523976108047558463843016193939194328299205150710713636374839987795654700562785520431848646007823881926399276079187761973753586338798650906578068870077914435317379113253603231809536000*z9^2-1172622246547062376172462548605466310752567160197724775158476182230307951647752343762996429856051596913587847160346451991824589491012967853740689469107858206502347101293434839261082050877510944*z2*z10+131727008228061559818572341114508294727606514136995460642805371901115860361257249120382948452641422698781374145859016962634534523255335365823202363407541790789966010047513458189376124530570972*z5*z10+814978520218742989333285370221031491214864463035371366531380762209862918002044326481532649241050259929340620159787454569140523347365013916744030695473397635446715396796777334617874594885382728*z6*z10-10564904601579657743248427967116772568277667957619280385449828815812301416263426366760344675998760475086416197269020480559479704042871613543579465356601912979104135126221118344937334613598893200*z9*z10-439025902594657850760470404554982177267278780781250016029426782773659682013105846891333352648002032906795300354019107110136114391267856599841007772258722939067675193606621989854455369517645575250*z10^2-5091928742273350398408597581096462030773292200422258374544608534977467970941692443275853090888148451391997106183691445699399151767946376713292876262341893914661415534820100705523222102585120*z2+96560286702195059678303879926932423604639964055020740813824131276982002553610066113681527538103306177000217063949624455077278240731060756869688602088407121694505635510943327807582671405892*z5+2521296731634009983012174606316887110667824365645499159303546603998772215509140537844554243174596246394406926620674361034128531920706800098873801116549685961255885470612350127711842181637410*z6-19568727336505434132232934679968453857391478770403738603048222328429113045864837189861379415554997333419164848406714971765957846762522593883533327338920985306965448129686918337769032515330248*z9-12901182124194039731141195652548452669880761000912747709864326417210576640908488401373653703141039002079898622005674112980626512344659434017658453689541683992530116141717272186435818824110151205*z10-55551009713193334516743293010083970325112094315271858998679997221856856178670525996258568070350483211038736943911740203936786896114610142461834371835552242329521938824071650027387275085511102, 915138079519799676619436559088407072596406231805820687600068046950689616891395711557904284773096233683860372277913173853287675059470945484800000*z1*z9^2-7348368768871431031052473545655269694216898798565646818851244617024059787093125641689132088913412059772042544634671701779176764822947131489147216212648175*z4*z5*z10+624434652873892306576084397622693156275733076327928363707949172815141665117099300268437020342038929542428946807258798581253768731964724854116769394600800*z1*z6*z10+844876386609100116823110843461560044331806227181152890126434922682271345293504730652491635665288220374882951911334302859713012519298760815155724902105300*z3*z6*z10-5585110017505966093969206987579370827508991098773285212505205679065422507498743248548094817004690427912153753600648155099451080866467353483208427211892950*z4*z6*z10-23245809616003151565803945803618245598442849099474788010449392468629426945582747444442912219169933752036917959763096823373162642061315671475305698898320000*z1*z9*z10+94589900904501800038203805568782665031374746712673773025367502889439900692532481119440950217964686381763890056367928136361755413295514328590843307676392400*z3*z9*z10-69178161346264950979086126118757564277801694706121401283689276590352896123267469250458726593785899783239271369133137711497980434626484254996382737947930000*z4*z9*z10-2193500383949227120268415744895297549846473299640998400494634764032751254182214540303281135495408666101362649628165197822914808214226383455208471045213984375*z1*z10^2+2207910588875586440166239086720212148560267022591647851733172369330767715912092121079117447358773310557750695485312559749027719853512658501523061298815625000*z3*z10^2+5696928897217948583722240962496545346694714884049242752293232983616171594152993233013513486038034099931648294330352743349812606304405295131559347661869606875*z4*z10^2+19086339581526121318296529003535546307419973632258556432496377097072238005811962360259738061372455087634815287674440841989991064660657670624188667483400*z1*z2-68845672522836482792840130560826366914032133476863698775071179718097989364886835213352039450010382627120954336453820139319614919606033793284772380458364*z2*z3+47169471119717730633737015591475736907443626851454437157480575398570509166530438997787671036205035591802584407206106786648480030630773048289966611090932*z2*z4-14043106703815644813541900532034789262582872722794461480449920557699179780816000835032786512928608316426851261073385322987724401543016126437090264814066*z1*z5-12163105502339939230598821804032792275937545946860661222630586605703278293817772160857073750286877208139737334082241885441062772182401646534039513925816*z3*z5-6248102535991396859110578768609231391695846134901392274546511815848616307759680357749424356073720993240870706432655929914226393162933146655551790359525*z4*z5-18772997866106309203265548652875343221385328045045134868986832381552467936273730151872224938604372491380005651564530582366336822112918357189406789062966*z1*z6+28684468028926945599914153491316476187034371506602860918941387537385193203122798348407516864794119139100343863481648501253808726603305891874502286062166*z3*z6-27434433912905277638455775297767882887875725373610640622978150071759320291083355010839178601599102953575439430654798638767725063878156431799895563072566*z4*z6-87209401901990398468785181194041769927977893735523492524929178148717872092751134087223416471383474493725158699885683204304304287938244763131685177376000*z1*z9+407000006706973830339425935131022832245616392506861201310373005114184844315197289635158259221351525861747851022770397071868676112061763890791644672048400*z3*z9-310116567455013609426528021763319298913355021055814500650411748093230320584442583518384525699366424951245304653186688955690907958073565215082024884920400*z4*z9-23448382903155562823775224157841780084752039704171095709881637178618805881742559274602817966136575831906357823075697170878413813072036759596637870828116950*z1*z10+39864602323745261375738882533293462816036904792071687394585378762178227248122435181757993767265678707839065177876124038865332707506647746839449992711917700*z3*z10+21842366574945547409310168326706997227249070650644312448153800773989672241221559700668351978430793453163772625851978065745355041764962879186337387647335550*z4*z10-52262772101845628065792069828305823548170419035137630335241002119066120200990702093764619972696511104003957602403424787525914891280698405707797846808175*z1+51883788288563707075121188987346211875330616295978208620961265466670250235607763633919829126981148653173494127383441212109760576963819815070761756367936*z3+60645417093149845281169204815683496234817084133129654602423436685512418232419453606548640010846466081708218208054909206261873543874032033977184593901807*z4, 4323178184097197752528153059818834378468972888902409966907247019858741072774101639965224113190476834115373574186003160708033884171324863153344267071337171870703134745273975209420*z6^2*z9-1261049500223091126959969103853031498184209954447825198156227277475347280873418790478351687877436633489422134280969092585949514224454955218471683147929152863179689477023348239482068800*z5*z10^2-2658206856569276678205078760861798290483886133753582141916291717050656950663610918062465735980319113332210643310922491003904540540881853534180180027373902688054415676957306079290996050*z6*z10^2+61266391965055163236070598383018774372087018694818111257170833854047519232386985824653155998763757118327800209831433275711304260829698444716309462852750035186307496550739295795386517500*z9*z10^2-6610485085340396566837558284771965199929390456859611251032997726378002052586982889728877240906658065215132401738324768179133557904466364337144615669696917847930146556608462421229647296875*z10^3-1030573075054118898522236665405997817535669550417086774227252809428603348229541222654890838399654458285857807855961858034090164798420029134870986762928746223042347344052917830912*z2^2+1592781026123482970984608491068829290939871222449228611765741064616634386658688663559309813500466934040262803174732083965597582149920029880858342270057690570266130232164934310690*z4^2+2797676344049507924150876833203302224885457572018668817740977494316334463665048241982817908587190058098100850823008966836987363973034666797034472448049559951127288464526519564552*z2*z5+1676222591290495434129335001327945080041380945985884350266966970054198338716294143966660014074516506049451071931184934733705251339934073364944061592920105105067962165722433365210*z5^2-3760918708555637784047030973057558383705258140775472893449710196036535750287271319621583118996688611385386143786446453727509659284690895960666751878053907802326935459920138914816*z2*z6-1533494821727648837647450589974303946230134522463817132957594416582059240908051669122939562199868434044119894780765127665060605223278169889400101209125144552509589032459537863776*z5*z6-1972128156521259737834310660055628309640592392919080947618323372269705820863992744222513916234344022193917607006996519358044904369591968184251955599835512796795271162609948618914*z6^2-10035720718008115266895338438750044492964280361225026574510427862642652946769723167159246667473766612092339597030141163120555033133602741402176536304089779849230434499828834094592*z2*z9-6809779198395441144592414876161019046250660792251961852432335040099747635912945043571005778157191719657506523828261403967899883177624653738710815338056623155386904808171671758592*z5*z9-14399372612052686704712326525523403297542161129933460389432351426922763271544550738545601151920450041566461081576969192032232672444554528599802530486091278590368729817197981497088*z6*z9-241274845035827907789128383358648697632886690647267592486300293142655698767771523300128531383102775371291570811062546952572950846629899910031387359143074716632713814179840000*z9^2+56511781301757359087789009135050063450708705700446831696517847573686957217326238473214902149373213864819630143704552806519895942973427101462534806124410401235378163018679355616916512*z2*z10-5983212312178988421351474009949628045105801320792228514877855671062648617226778831070386943712336607267109910466291971724108051195241433396435204075939819744210004896273398741823516*z5*z10-40775535905332069561775485208814260397555190036734627711954149979512312459846437212000888465790737346959428438585704648900912252547639024812009992957151274576690529911835809092528664*z6*z10+483371441885514249611209633192518362930285072702532272615758988439348274983102487284409934286900228783714535364691775058782968142604812200785288355104563788828867861261046626762852600*z9*z10-50635808739342302374329532984343200607904724007667120168899832153444919527988184660428398687003226776561880058820410474721617670879394983187646473233398296222879179619467477201816328500*z10^2+245796136034164237182065570845715843815073862001997828764810740125824353535437320980226181611649561632798345765627641279685670104213761972002791463782836500183830767577662762802080*z2-3672967188986136159253403215636187437528072900199216455732685741197797628079582001638764585289717187367276347034716365989347381996474470309722179679692652690888059335725748939956*z5-125353966929596113247026510977298788801830464762838593305400437498328787925038154238419907430614096213883284668322604745584948585659760341109236896736899089986852175031092195773270*z6+927641729482189414421915067259130489993851868800010170200684352037060588405047834712598921811190771070341766200482747743753467205472977610940242931857455021718063311099361453536764*z9+110595702738043459205709976129764002762703478612642189282922802907919543718547924430872459745790060609383520211209266433775507134282534200926104069526111520488193937073084393284339405*z10+1253845422582070901690791440325861325910751953174731642153526324657070579941876220664932969170261018211625376455452972055429103075446636215673719047192615054899052221714136395062536, 138341701891110328080900897914202700111007132444877118941031904635479714328771252478887171622095258691691954373952101142657084293482395620907016546282789499862500311848767206701440*z5*z6*z9+67040335862224841183416802579679548760038890890806826220324532465292394432753476656297543270423328985189445803335240298263681302261705147481438442801452528956564542583198545815328113600*z5*z10^2+154982841522119602290130755215589681974643408198928717108425683225719352434363528747528030890680408109210377333776726220798260362302012924477703400921725626611579678246636961684745938850*z6*z10^2-228431538273469893253612503240183648746369930070998464642570362226739559414041624662874673015371344015177821557036272948832927177614481579362650554321594915687480382293977227533541135000*z9*z10^2+366021111440469557507460355231644899801122461524332561423588367430357641511709322064364451404437197262954474196624608903362568923917357516944819638425833794293021464211069769202564769078125*z10^3+41124757611039869667418990301077043740626534253114426964320119352571805516233387289761127618288955022340890212222218947119511867500726475927775288529000263838417888880697608108304*z2^2-93691236596770603924864909176762466989478375188091510258312392491016495251376202443964625816102114052472106196173174286949511824839579160560384313014628206450007478559669168389470*z4^2-193417773737932653092478498594322563084203213055611410128248474132603555552808181243906071563694473060580205964127516149795668079421896543589479522723322514038740365987664182891304*z2*z5-100095732010994183816079179634364067620410005319981432997747521855525132074946562521218966377328805324438440815343545194463966291332199338752452625491001819257961933631474293099990*z5^2+257283495295845488545131022106508104408870655906269855977417682248832499983044891203199328280060902115527068844641998823599780983704917366104215754876049362986673168793646004810752*z2*z6+101988289338428381140883845194938950041283687739543124196508563509756858806129766197645087657681780337913375048323510768357380261766127072019242080444312894640996054003370325240672*z5*z6+115915371963640486885179957586406136871001478832505274371631125370543320914559670071893462824284194205367290211818569945033865891730709322792232080986487102765463090040362285897438*z6^2+608208973307956167683041789993693204567076843083660348057377701862713737345476091783872733180968869391310224418378715142806760725145194735595009049144154487002321428437998813851904*z2*z9+469423578649187219957118943810094934981541177738883760748201719724254906878909752956802922525983367291889200398121784879841404778032841693671729466679429638244178362376000514322304*z5*z9+1108347673386473856144976948186170486621311663572391617442161201769401138158870237373046753281316155036155697109506121643530579249567831217570221203713969983148780248080785272776576*z6*z9+15770119523777159426022378917818188755855997930201829900944762132109605323687689259348081527852899613925284880460905842505592895186664600733858248391634602358373546993172480000*z9^2-2997468710124432644185082794477057893066036009811121552935199378392256180800136294562916456455425692048930485737568906496314345349525852264476902552581993936469721830693016800635700064*z2*z10+347854506160114109237059672065876044123887135032978816160213628233123403486842942809747525645054824207912833200824637270731562157425879274286120259916186427674113678234949343526704372*z5*z10+2395529026346625785544493200994259562630844987326420841802127468082564829274532939160471162158015258888672909180714820070884037841422905724655143026942744457804254379644895558718710168*z6*z10+500205327058174936927963086133060977546807131899925082122936786522336972130378222778691630920924715999474937213445396722659099744088928541270091392718188244263773984489424908030702800*z9*z10+2659650611068260021774709817386214125201488957023723572839120209180056150350472956611100505873247591787812477981820474917227204765044965393426059163289398381301774276406671307164845075250*z10^2-13146701542913037646161655030357734544916722768497585748773199586703299876791647695139298568261763724107650016066748859973728304023468934065689138591887087477582526029156145650419040*z2+341110344880624777184822356095593079547400200171660140111221835223582556722621015831423010308857470748917055443836184073907905758562821942639697341396328006980560871179998622981772*z5+7438335283152305939609632825159069791956514142441514158144118663505307819690511780139471628362749258385524264453601157737260444290338636453962043662959476582374446414442536560456790*z6+7416386201235063013823360446548479058108663432112441712107097094891481708261105204163102618579846976825131468416168393551210396742559637250207277307966320343652620305595553588052712*z9-8215181061999418816851837653020356870216281199296613465192361174114236960044048849629089008510237261691098015809402168107133815629036509362073182378009716063041755803953873609636739695*z10-77274577851617121374983297941805915344171518452804656667762165639699290059174997137252183270533089029931970970661154836715219268758423211000888556648800408992858754851259126133129042, 805686836364930195310930781979507601919156525193851250246690944597367414529479471959516244490237657433107636145740800*z4*z6*z9+56062782428374241269701136504478054862235250499341053958989929482120584480471481326102705748538870446303751612670247117025*z4*z5*z10-3505122639445304735560512131670309260382757161757734025290540815332561111357866764996996020972381313177115612251092003200*z1*z6*z10-5228242041657439289036454151630494519434661196484681894968425168479951100418411313132426808641419410064971298685506115100*z3*z6*z10+41377779840123601897478171009981858285905244638126924872773904322942286908937596624680385492436321950774098617319413215350*z4*z6*z10+166847120737572556476818177535245125932774707755155686118142395125462521959694154047257407957856426249865164325432776240000*z1*z9*z10-754227447450330080904901654282549918856329875691170838800275313944089830434133852458150160955447056800097977061066664196400*z3*z9*z10+572721835878459910544348028838835446243463185788990675609275904264948394378441652638778112119462859746994354335230174770000*z4*z9*z10+19371124369743686557572562422235086885333108820814803543801248949137714966227157355084038749828026042602168262539876111796875*z1*z10^2-16749923423985706721172033793068683082755307769602083991724288943607446413118327692782790217847868390324707454197718248281250*z3*z10^2-44195509093212277831045943701719625993495889879832238522647270274576931039722470844626336421524223011249179010174883584590625*z4*z10^2-146517679979796736669557232672894219865548821073615501892399689153067510439427108088811311142391172518077989451450842400*z1*z2+528808311742878968882057406807481487444643114123119739843856767818011356547157084966363524622024389070406840160694747692*z2*z3-364208045915859875567304309069065545404772818234920737565170638837017192779523490613745822893484270760846534825479302796*z2*z4+106788407420321359881805642120842623165947854566476234310401370228147383774846346917327330004307991045468893740250677998*z1*z5+93108031858779519963506848320456389318421710601156949121771748611291684042191572377239527934017043426036376805321367048*z3*z5+47798510465443853092406449796764681553961770600543856644959454491578922276005345262054287258768398964878354699510644875*z4*z5+152533199630194206079288230079433637196682964723201143613130629132165753477527912425398760770527245303370496656994132598*z1*z6-211952916251537240625110132126658105806878426769377526560668090182390545146758671976209896970685479446103887154924754998*z3*z6+199195749773598769602906933238670548716627420758026991640267889875878995276146697547215021682184424528792699081995060598*z4*z6+598046084968438668654485284642486806836724517411673670711101347586524175360193301276603230399364396262729683444754313600*z1*z9-3198706455964761351426972599416865702353840762775744585907182724717225343833520337248171616192437250219430307757718997200*z3*z9+2535276555189802299627944326291870763038363667661539894940168724526475303131116526866429503515588562560003698659057385200*z4*z9+196636207779378939789354850598057051948623748511193086872890498060118007323264861510910805413060227827566530886365037521550*z1*z10-297530328945606324475490676125256130825489111315162390650543103695121962998549988164295643295236774431148283590470081817500*z3*z10-177642006512024602429816666725525383110873017190774361264490934888495926485149496830699176650844526922246967861923102567850*z4*z10+412848860770209409979890263701467872749555099697540972424717002362698097027355295383847341010499970765431646318006515475*z1-375439439825197654094932717540728757130177160883128633932395456792232128872977596031535722128336896128883632752767501158*z3-478484227409847357744953972918114979343875726994307250675025074380918476393822706417399255404280588919895828442255775821*z4, 805686836364930195310930781979507601919156525193851250246690944597367414529479471959516244490237657433107636145740800*z3*z6*z9+56005247225458074628659514370815252517058695490697142236912039716231744689597366518596535926498128044876986792479807803425*z4*z5*z10-3395309777808345648590136005335767369328686243609370321989195018078272274065578958617257489177658222276249811109821692800*z1*z6*z10-5126382500647249942683254645368594544398222967707081522449438141692789672966970832603152585498818967826453678015099715100*z3*z6*z10+41209817476950291373342806113456551138906881438464947409047513546902001082772783422671088652145192886667443134467002916150*z4*z6*z10+165761215255704261548613856324175347693286219558664746865359564054340946187965876180212255879144226667198184799776302640000*z1*z9*z10-757590673404771271758475240933748771821941440798984993787882768177931680829972449327363707592252979403083833552965641758000*z3*z9*z10+577218473406594609800895755598112866342132565548297337717875451397356612867003933580342004340832308196382514511585980530000*z4*z9*z10+19689248926105888460944446565895301585567417381223183785351179293124970286067614121580506915430608233168808473897775054296875*z1*z10^2-16953632687467918665484519283636437258036204439788415264071582607697619277519961510851623344860631265636956458456676895781250*z3*z10^2-44373826121106202794192154390346538292050765752642962934519790557893738101307033438433587472091173312289312951000661661150625*z4*z10^2-146505312501786396584054324458709809828401825589321726872430861779935683238749221140389854178310828158166355606675684000*z1*z2+528305977493279677156519461481497205084356629550106810596329474505923030549758760415128026758145518356155200224558582444*z2*z3-363658565837740853862906584848228121260283832350953798099356476377713701613936060634670192286522162929714557311808792972*z2*z4+106598772758616892224908297478608433626672102099168320199395889771546600633281044958010185953055720648440984413721087086*z1*z5+92889028171815162894922911596156939848141423977484171173648850814449609928501271222714788366200915137146802038630320136*z3*z5+47952718785191032779893083757888477044539407759144112723219290509939031353721157155713127292560033600115331566952550475*z4*z5+153112048659566655515230014358833219161374553088600219636261866957155086929779851962783506098127168162809662780434917686*z1*z6-211243600410549862749419780094293443256838786019640612179042531843436723619498324585835025707800832715110900988031549686*z3*z6+198068441724270036593992633656117519038415437755627428143718624961185559994464758162155453636469763769916120168686431286*z4*z6+593934860959446539424550150336154905811602192307429433828079542793536147829681807015734286105503915848605154256287164800*z1*z9-3214618441910410705615758532980544023173045427688913792266656471740605017747744136044605498326881812040499568545502485200*z3*z9+2555511730175913782935936631055912744572704740218990467867441388603934761943658204869148047511003118991410349787978422000*z4*z9+198956861074545018593988435071784487246522177085504550503496679875709134109166753065336801864095886906194294451294417279950*z1*z10-299688351146585806982881028409792120769087639882843445221280503782807386467909263980929465377853201506321855749869639475100*z3*z10-178626899563843104001461679289231092160939271776546488834327281020892372895547871613361727279183905000694216851446196865450*z4*z10+416270616200369306330197834228988910399412956231312111170932276256355488622627216034910363405309798033548623747032356275*z1-381958746959683162065053238641868578073083983363963863002034709509527832392560180522371908775312082966449477187977808006*z3-477837956906202822668810685604884665756679807234185916590626864986525573590433778216596442214710238938253192185251701197*z4, 17292712736388791010112612239275337513875891555609639867628988079434964291096406559860896452761907336461494296744012642832135536685299452613377068285348687482812538981095900837680*z2*z6*z9-1752433330899070564828330306363174513294598852649005814040530129975561299657553510463745197433835452640395923670682047717334716734652393459897412944964610635434415519663067366097582100*z5*z10^2-3702873650234937316495487242147215195446623317110676934719942864598285235169439705705115791833831257345044139831673931084713493759134041729169985960940249486206264393736246337350696100*z6*z10^2+74270705759570803902818021664673967053039253317341266531601715289529482067255227100459413004971464023236068064896228292502549668097280329964774285632522384875110924543346636925345866250*z9*z10^2-9250140751261187027755414950905760268904665512942193049718536074315978869408853207428661112767595409551836766149922473917002840313924090621706926400524888974504324823794140186525727671875*z10^3-1187020207036491048169392613680148754371298960409128164323570820001982711588021558774164109985087866106912661913905376935986296732386210109967876522190315534965306919796065304864*z2^2+2150470120717867607569284030886237847596994103986619896484443638989857947335040524644892264193787164755415805117865899002094706562853777520587143138308267476808425504523735462110*z4^2+3970388014388248509410291669666888447350156607845560522396181894366550623546078799721581009665688466813188889187781383872710977893494758133770588005975274488049372355932183976064*z2*z5+2250701737455317827037997281301681146890293678261682868949149910688199960234758775320084932618102093846660978706382326235076967362213998889638589914516670616732506077298213961910*z5^2-5386254140567925833327677763701201682643186681864884968999328543210108723402648048009776358550282611855717790258221557385927463163278815756533202795023308089707242075007799365632*z2*z6-2196145287856532609569512972530709708981514303531114040690726390359569783104306439958743622214452607282935108318897190024196927875368966932508842232083775545029782568711965163712*z5*z6-2679874586024879438523422166478399351897206871063600697210572402602490663820681629885707454907459392827251595507120048290208874975476233867358246298929367223011404076763251883998*z6^2-12893914806951386937696491773799468715517647085140058074855841025410319579395062385620128083523030783126200293041015484136215428933165970526123197256207557369127979209276442689984*z2*z9-8558986322696023518025978169857792130860353230079850489339233233492725320254634003139558808569559085469753003753244384200902284936238816773837128469729960142033748751497685561824*z5*z9-17947089070845528735970851522205542854917760250375479633787440040124966719417013848314381809187233932875873516052241661817413558937207778158997596844217696853263421012432525470176*z6*z9-303401452962733280739443684650002869973295616292438992243014564346203096346960896117008218540907613933703711522658573447605843129276023657113381413860222178019764261498880000*z9^2+79171708614100217494754438693778399845131805551252004313834023169913758363706903467011731166895124510966705907264153055056019566106874468532289436945929122830992629084404930502461664*z2*z10-8235970665433856603195619141864044057961240484260876514976469371759948918563727468004812898811688311638873707095292793308109174746606539249329383488737396411501994020654831790644912*z5*z10-56873053759527362022538852524897050225663920449745382377672921353150962604704348202635395615958995480281461696406252088318948256150178898674993558570224711004806161370069741020625008*z6*z10+579880403182572679360777163319256161624850026639055143184488349987860405412790738600810151111601143186055967937077541261624886130241848810195839604357058869894401218724221717613655700*z9*z10-72446302784270535520266371941679225063242604166335604164823927865672216519108608294197492616228152191447021432135603532202343177618138830111932293973892290088142791399984899700424904625*z10^2+345115912213249255621631563892184346721395253618522550982309414001641866269244594259195858778952240935218593884418831849345102762358660937580275873662065579535424887069732555145120*z2-4709743949075343711657227098234447025372288152895341867848973199702935331024508986220678347149692868896810249322932613280569454153699248774612739350189596110587259089927921175772*z5-175169975755143194628814106010224432609594564012073778132408066965363802500796694678356161479286719026111643176114823570359984785230525882886192386652542583200362787537786662152220*z6+1096949634847701130603484119660164608684263044709194842576481381621041640280328498806490820506911598193260925311977489955846147099051985994076048932158875349564996814644005441014698*z9+133461680210972590906577334536191091978499446172843214968547902417014773561743695354662412226744296505268903232157280122076351313779536105116014555967762693669563226557306897788491795*z10+1674029834863399618352709599218910896277403276136735013051185853140154445534397253038810774357772304390464961865951507465115744804501570415334754892488625303986888096674264558324407, 268562278788310065103643593993169200639718841731283750082230314865789138176493157319838748163412552477702545381913600*z1*z6*z9+18461274654564625577678806562741452544820180243287444236669587593137591819299227877674047246458203432402062026931537168875*z4*z5*z10-1107537680970834550877740448427107875577439935988635422559846622714057996980594574987764171711388265038532215926169590400*z1*z6*z10-1678716171412756945022213386083782030829314505406023203230395122269445079173146064256023486983677450665775811729818261300*z3*z6*z10+13570514123077159292445596566520875826413790037473111419896799759588932155367498007401166533683190765164770661338358452050*z4*z6*z10+54694707821133620805810199466556783443366254915089531060107188793449935977270780837159299120292870099780021396997254160000*z1*z9*z10-250450047276118174782954859219288357330592886045778803507718452433388276344686889046289448714253207041613409633341835594000*z3*z9*z10+190870681308111333000305475666748307104590186749859463382870315122577667899541530289908602443619568721247692739135627110000*z4*z9*z10+6529796163145990640935949865034133664018580946823587725733251215277687783797026347961831240231790205331892984779321392265625*z1*z10^2-5577879744978346871390960064407435308597489838634624462012026919806539310402356625002431851843745495169351743334360978593750*z3*z10^2-14665519053802680199193182558128670845320409314453944804994221136126922018470942565543501252925040313420899377042775311696875*z4*z10^2-48314832384414587858627944024787846897269601054666312636576311157254877944597110488757960891929862562425957905167039200*z1*z2+174129350249298384521525110390990007399969021944542354984031702736210488356748520275568530181246834008510490006696088932*z2*z3-119851976474244179423907628268430479466415171156618329179356225183398472291531810959649789183993020209207449647722042116*z2*z4+35122786906431119694239104741298503012657419762612220598000327356947038036525951435405581903805747454587455321547420858*z1*z5+30607726137610618772241144544707583121898751287616203141536634795166350256443563644569010907323000708388214950664152408*z3*z5+15835192754041342986514955088228572927687350674751526469720782742650048556938899506006248011197040258480780196384074425*z4*z5+50553161522749642375180125670806557475057710254997228085284545341164689447690298939893992250942195537146264831096799058*z1*z6-69562619973869646206278307503331879002397675880457082570442040791711062927039779203264406449700242698406484539811418258*z3*z6+65187053020985551138213738440737223320964882967259221543872878764508262508227861246135859106732472031042949302889291858*z4*z6+195294505820570919435425211917594027124007697002757384766852134359168987887733547801425276450252845435903535023331920000*z1*z9-1061989138091770437172897769121722036721917924065310431799170629993664903303085151286656251095948683899626871155515394800*z3*z9+844906730601344720595371686484818751607441725723490127584744211571355898316213463208664316199480158774010251243258066000*z4*z9+65891202524001884089971431394004974147685314647912861610236096592915188842475369639712012795035325933229428954610974677850*z1*z10-98664161382722486548114956374407800681371592100520898768264777314466593512158910928936858726960291743638447655405601061300*z3*z10-59230802821454296828867169886594211149181254873997650630390881838159879637091656896836357568664549196256828526190458332750*z4*z10+137724353737306736986900096073636427660698859360062120145950481996712264236494864032265224789550100592444185230775565425*z1-125629390458848289131791402901268241752519002083989370344243291031592999885690955895718820611334358863937183234661561218*z3-158194139712861642474852176661667695585047117609314887988922916305293604372064606910523303365611333987037940649833853391*z4, 4323178184097197752528153059818834378468972888902409966907247019858741072774101639965224113190476834115373574186003160708033884171324863153344267071337171870703134745273975209420*z5^2*z9+3287682565047707785091396511860701890875931638084849797442878842405348635196826988644992782555378029225509371789015433656728433560686980215525079097778238640507018158769638379155795700*z5*z10^2+7281369323605073727343649936895889963035822285103050989610704325298790201124436585696456047888828528150183396740447782085715057539193504565288512835986745203337678533075924872559094950*z6*z10^2-79250148539278520891410480528924325486218328227823087599710693024256189057671491655719491255947197812689648042236023754375345739861554285129862441920195601775630968867352349565105907500*z9*z10^2+21965946961767415051989722023225143793082711204259475031963485150048944616528117088826866362494694872260274431295818052262620426344690872972441917363839591774595294528717621355033153312500*z10^3+2919632884259727369928281198597626546610592755073225588652579127104612880755685079033817538702808600321978530468418430760031660206168293508791476202254011166102827181230439659888*z2^2-2699239593599406952442628353996670361197893968395370102925519790822280610360603882215614469842137455788326012571566932293053450511132090820761924695127831907344731223374183313940*z4^2-6752775527281744231305110154484966133986318786683809564428907072877197421625056299968336564264291011309445603084062510088421857484050033129573542841280275446157163880413801267048*z2*z5-2945895024199084542835405972228598614387827766157489502131812168327602500905270914087334894480021218139261834820903300838841415191574827254256926182464259479990178292562376850500*z5^2+9075391234938201772512332769997552166450059366720639718048052581898864318638434877755933564851936443009383332149097651856065427711566925574109155864707560187911283795585829438464*z2*z6+3734894916445939607351319773599239632472600190046679503416801234969897294228311172549106182530224166464844359009800432294861184499080540213524592665664962114503475135007764582944*z5*z6+3702103074422255461058284956339422310711062071389592772965829920052023871277877655992472375553504473975328603984689346166843843999256963422105468589705114665000996041029803340436*z6^2+27629202568987265251882105073879265172550070770323570383563380788943223446433880915983842121381110000025966088894613464912816409801560129031941672469562351354960921139052280832128*z2*z9+29305578573752815693860413369062854260478826553292594976438707124065076774057578892561250651226151584195532651866819644295080124239839263799295880001554884743090924623966908918208*z5*z9+32922788151490893500759294700581009091481956649845747793924125181160545861225084176795921523435534743994012747424908803156874284083993546412058972357638104102613418798522422189632*z6*z9+681976860391517122819488306495199205461683114173475852109855613137289358526075644202724570762880881905929873175988785557957777892015287514304147556228245819585790444380160000*z9^2-145891520867901668522456278066661305431599929137460603818824279134078119223198492088014910347640322341897169123834860681609898809734678536814032523810734645448333726436922614960986048*z2*z10+16861046443721718831820593395497836607138656980022242328806317762949800456464099493726236114670583926495947841518611145104746858065625625551252388505883179446592895389482522553103204*z5*z10+110879185721888987492472522513786890970195570203606140643146126837778041155150741021774180125843021784546273694450084816856360527200045868913169498693018570091860904187933907988098376*z6*z10-586017376555505390712739965926050858020375216272318545002883059672269773919908850787477711929306073001328642310681786075181825817224268461553969887650568784307047862412392828647597400*z9*z10+222144123374722668943685643209773799618249602313682460790772258741140779229387987702196463239861874833684907428493319589431589139127282804907181125157730376208585610554354155767496364875*z10^2-634495507465283741458086838694155659037745962455545951232547557206215684426088220206904145250822120691523454197298204985354146011021779780365011962643578846347067468081115865580160*z2+15084838875665468603083800745554611173690636681601403944993333849402379401613433734333792584954419410258831104706267272931272124064253457269369043792199311629726273211936707796504*z5+340366524385864718201002285508394411876679957808297711994120150366747345909570233893783230200822656091956631675592731594898041182633697373399383248792882932289786926479996714629010*z6-1005049453554272891809402926435016006932253300653577633035866756608289441462074859335719108834708613058212564342178002007852147971612625845512375010546911015586325225581934849804716*z9+371500550911430535653505823703115599718629610483029120849081146859449250888697223749204070035072174342155699092771184453745535183456581613694876566256600482747427889140799891817240210*z10-1373413551377119481753989437722466797759835261707770962232307310068007309208273624787854219352202664702628562837842421926855390262131752451028548843860819804145972584607745304026929, 53712455757662013020728718798633840127943768346256750016446062973157827635298631463967749632682510495540509076382720*z4*z5*z9+3130282154198594625685662921922788400499783289578906913150126224955136022575152402662068170330750523156927277128862575605*z4*z5*z10-173320564766809673714313921423151822053147774659461657057514419784192540993150000118561182618486407264938301230588621600*z1*z6*z10-261905906880144485762958482973428773092749108487705629920579994562894557948805531219829269762260260153920901057361657820*z3*z6*z10+2268710105482668285604919078263089294153317213244195383162712467285118935839848120160686020876929338371274733007402872530*z4*z6*z10+9599713303530651349247993490285197850484972669554305217737007913231107624202779351302730746468417254293959394744842544000*z1*z9*z10-43735021137543551172063137798238164652100743155021499809430061673178217872416376830780098648664740290801304835824433275440*z3*z9*z10+31935380897360174626564212774978518139080036088161800596690876794143097922338857772738257242066827486261904498656998722000*z4*z9*z10+1210352020556819790646110776154190749970027081894749510799559736398224184586216196595365588233077353596939594737535002578125*z1*z10^2-985261605129789972858936634855906844906015785946304561285278300455261383102143927849147503406521204400552538344614843875000*z3*z10^2-2650840011413404710562431061184684415259520814905448116427362061289220316231342001224816475198361281868998866872220429017625*z4*z10^2-8257114667234549115503306382333077177438572215885887286769992231382079912537441666152425381668775740423630812762430040*z1*z2+29307905857320268641806374832688577459352024362178222220897348718632929766432699245408976497410173208458589133200517524*z2*z3-20012466220496377877791893725532163315641731925076962256218595274492813469692398523077075290277210053158170658534517692*z2*z4+5882697368899359516248035663117931915679210246218135118629857638284039289642520809182325263270503392098878618200668806*z1*z5+5097713676905219038760666934603453467328344425521497131966032165847177864292218422341548132134048023503547855506835176*z3*z5+2846668959278479516000358289912753290584942717835057635012167586900110531948217588641758064092246687693637610625111655*z4*z5+8646230861483947391316448842972512116741396711928515713244975665361370563572239372007495474584685062994219597517236466*z1*z6-11656368052085032245191403264675194871734618266535850383805256020608104424415021720082879307632151927222519286748917586*z3*z6+10855929618863409052194050551771595686423545573411334696284456413949002858963673752156294209027187072974369559867189746*z4*z6+35130141864457599398137468293971777719793834408613296080488854057180687439003021165597303380268298423084272943397195520*z1*z9-191710964232530935822444519029407319296691857555956456585229158977313506438209576051946422026162558091509695043589320080*z3*z9+146815274283783916294543590074162592093783231509261862308734023590546191156945052744187094403008334898617008468435742640*z4*z9+12051948967709635876595128844650461042490364840660541911445818330586818253473862124111692853088909294981477620316440501650*z1*z10-17583280124004616585294606129742398680112636506655564266897300226337638897019815370578076529630772174327552840527402534060*z3*z10-10971415599870055801539738895975156149652141122128325857220680977144423225991881726253147466824556083914292076558166606410*z4*z10+25137094532735159951799545827974664463027330836538560045175474594644403913307903161579632100455582271749990780349712245*z1-24480900495968685575935364884594974108055027827093206841129378034458036135969517390853924346547759855995607901023209536*z3-27501432265688244741233227411460918883582430980891028585259060314178381538056701695919330265572667390408489692201947317*z4, 268562278788310065103643593993169200639718841731283750082230314865789138176493157319838748163412552477702545381913600*z3*z5*z9+15825263244920379272376609181048362390979319896974583924090949713865169852108529665034289225274997751023391428927587911625*z4*z5*z10-908815288218020332808031214402114728658323294517870556714348114976790132030469047924180603630214313687457969172114205600*z1*z6*z10-1358869183200672323538563903390436409809166487824526828628361085841303677927832176744756467363922500634593858903420961100*z3*z6*z10+11510384268030487110007972710719475219675260430761214713329157802416663547547271395009881966058620052464215619819578583450*z4*z6*z10+49128153554827346657380843094553225077466362865686793230566621464925019335447428600505784544378602590020645754553652720000*z1*z9*z10-220459193145718104792057147908509945901952536495427653861357632438156136840877155370500207336762608727734793714126111362800*z3*z9*z10+160299925618580214434760364810009432122116064254402888490300764405976012469114904637192913751406912353148769049520844170000*z4*z9*z10+6030606853842835598754131743035321107065933705188250018070065313174141367542641051175528250795131527536398271888987057890625*z1*z10^2-4843755166726813341238976148393964661512139625426976473756472906283081185433580321278797511956871235810894534188581104375000*z3*z10^2-13372108513026930889066868187468506210259089120000325060467568099083905764300722910660697658994937988791308508409285203888125*z4*z10^2-41689086366837150129088385509844371370708455666623076501002659694477067023894280926798377810087688332470310722875247800*z1*z2+148162120989830434758763684628223706506180346551089038182936017054674979070183209285146001317939902862460143114493679844*z2*z3-101210120578101621661120045006162765596129105473091020108577334317337834677997029710712491759318458261124759748982028972*z2*z4+29767191436237986210159718591389240427775176615521594686368376128454201474699381545106429885864728198463342364456048286*z1*z5+25795834328374875319477487991521699455075120731318221651714480711150022809733876097150924374147731790895892758366387336*z3*z5+14342187732774487249615170295661231741962603640017987210250650741774496315616204529426293932029605706402520617245775875*z4*z5+43487851158042252025292043829311609951408138760583451786402201589299831210173032593325035886719246307540299503455561786*z1*z6-59126249566065827889075968278261202139430952648824294035923294912951754015502120442097240226523407302454318882725954586*z3*z6+55173635511045256269709253548109887835187279309905284554014698277169023715340973166548534600759164258827784814846569786*z4*z6+180300545793466586146800133011837578326426264139024677979281518941358702640462723913883608996886731780790734786268076800*z1*z9-965749343855317847204173236224530072378019585248070129802910657383442215154368414918039224052299641089737525616488821200*z3*z9+736480575176084431364842683052561017080457019658901273369337738378767651529282152487540751975805370424199894659435698800*z4*z9+60311165006429551375132931933554223100338796014405795853279497974124008614744149823010807288945689050282995764250167298650*z1*z10-87155441544185708759990789669001931803716990830046788908274473588880869500702614476899693611817708069234433765501732663900*z3*z10-55822634953243466433815568690087815640457881048091817010088477991953827583504872545169302355662184042017341420713726529650*z4*z10+126317801583053281703247261250667918042065940358770166669576499848707061203145365743571519896250560875660165119492889225*z1-118629250674081895856740469028755489370266207630352013840447588430408498683862937514080203809364130350934268424561344256*z3-141529026683098553315500098339559697986055359860140679121920996877886667562064393896640238272067865342676895399169426697*z4, 138341701891110328080900897914202700111007132444877118941031904635479714328771252478887171622095258691691954373952101142657084293482395620907016546282789499862500311848767206701440*z2*z5*z9+12030438138367564920813022157996873038839651612169933897602576820943779937209823514933561107717557285195480230090486106998289011554948534571280434285152667723597369952936311013150203600*z5*z10^2+33539403226153711509219162036135005660097045218561420374060249032325663992800546838334346479184585297930835597157927617333519063746221037489107785299648968011676270063537648265798747850*z6*z10^2+112681701682565830627844902724086228967053771471867963994563576686508450993611473136134205343383835721223264106059224067275013109395623067424145625232124890539617242360160888809429215000*z9*z10^2+74472844444163625073823027929271087146269345202647749916978224545509936874697743571038875106196535814031082140894445139936055599186761543348120484524753452354021127609759837837085174453125*z10^3+8130459594066709664787988062947284684209634140326353764658016532785978559693796367765770582014650155218123255422960817608525043002431931866565930127834778083833082933017854630224*z2^2-24155122022156647360246762797797505252347767526380995160346032884416319437364077062676362739566946891863594293367006930463535684258095065193329652809431543698542238931873932781630*z4^2-47173165667549569360606731405654521864528885257125189162707261866701994598353246450853389601337839775647487445220469477384275209594457717868779129664922957790008093168922032422664*z2*z5-25989708288213195058419041227046350028579582303783945093424044338826165440251488308301474009860173948620088249794320247141307412921659848878981237192560035115892851979858462614710*z5^2+62128439516658800237697930403772147453545248752218667199904883033440344555132553371953778802998411621013724116436807112747809050203662461985484907844410810260199072225280268035072*z2*z6+24298611760868522203403831278257011847837914174915132134610659798629801418600830307539903957621112090767132293624864216628861214520873926440962233088982365805442019307600565094112*z5*z6+28956201110797789631106848048934150761467065106369759335722073715243366671814565688246589413404987650344474641969000393245015975233470112084889627815659944164760769573076825042878*z6^2+279408617452262179912390866505968670105504188554853769652395632231005954633966824175692110720753288531463103169704634111182441706359810625547649038187926494995896583926597918450944*z2*z9+108069569762184511452978063036105011043732002145299998563188501024636127589593197071441903778320566096140771661754519757317795091708169176146778898649773737679761889564883760052864*z5*z9+256793029559741016416905361660772774853428272741934861438802949853406065886733358958306671614332446769464028688023657863394068160142633984641230125057347169977101439842825374983296*z6*z9+3617196098793473473741155161185930443818722531193444619788913926224894848746700489600864963454481669191023581019915954970648069524572450238286268981096347737631384707809280000*z9^2-611456813227672233267440384707961701234103185777151524355864887910104448437431297405429743418129979804773106260780357035868175925421201612082770183511420059852742628273253812477123424*z2*z10+53194612603033953510463916742487173387809650627708391529004730171333493114185714286906906134419644934096451818779251981507795710999976836989780577016633182397339528483033853129073572*z5*z10+517443267318131039776220354242296519112523664219430880714732744541217903028346815091986647114029302263232459942488288865630267751311499776357920279968350216226585343055530061090074488*z6*z10+1585814738649318665313272332200081970743915782628335941075694247785816114707922537320833342889479396342440956901843030275722894435702966099661131337004485761718443499423824935576650800*z9*z10+424001889514663268601844926594158790968245363197284390115830414964125192153779031949233936474582722970976698534074037351009622735120853423580689641323634111216768033136557191304193176750*z10^2-2681933056491805971515444143700058159452016983715908797445043417903856055336642684643491618339074781724340504983544459804520650148956055155757932276859082014419584398422119045341280*z2+25548480123769713516564055176923385824783422147529026074389330501446361110922031679370287750098667893667869567249944632800589887682713286441159085142656997498199955436502629036172*z5+1605233819090013727206616456180661860189828881849979044581313745075594124587914794717204971711509561831152037257325408166964318506728629274447143113874617332632774360089374216294350*z6+4978768520994377253970313915810090854440983758446110091903327278526246227259946053863242313292806826801007630711156807701212836723600250962010637628581993328515256010195253291293592*z9-3247733578347352787119427403556216637225472276650823845400166912818556103379413114000666691400399305232866209996676791096953447183940480806532003178692029729020167542313631571046396415*z10-21549255380238245468669823749329845978671307787190742007112632741095606782788308641385635170857009699152442368516245574741867502072414617847399211825022108689173784330177403005731782, 89520759596103355034547864664389733546572947243761250027410104955263046058831052439946249387804184159234181793971200*z1*z5*z9+5302542383697438260718343180946791264972155933190755903802086996434925232241801598513449984482968613365954905102862714675*z4*z5*z10-306677255828966409778004600236071364987953365977271576077430118398965817995284695777814573524808445977565241663845356000*z1*z6*z10-457169689839259775778510854998031807177357588746190699303976008726388994737259185962883873875285784564836071230613258500*z3*z6*z10+3859151520546794560944501059922074760453801907506815564476865920384942684253879905211387967907432931466041751084386428350*z4*z6*z10+16415694933788611880791588402789010100526887334448631606208519154326683111567583051645373212109239036860214032369602640000*z1*z9*z10-73694332979653455460931358298805969475499722216870164814719327891240012385272284742663538055885355299870166542757216178000*z3*z9*z10+53607907851171199561467517919091670200757976510496936654225266677898187130851255205922124383139919864300069125450798030000*z4*z9*z10+2011931986468039259437802233079736745218871024796736011543306920882458787870050747472781707014768400009960881641799273046875*z1*z10^2-1635755745381185976358368416709202519992885127979160450852071050255452294287907491102830482038171285340145994172889258125000*z3*z10^2-4468077277250565059617420153433713246860953995554738412666205161371701609603534206995891890475639161873246094971666149299375*z4*z10^2-13965573189217304592297549038779903055437326396769984245210577316353801886244880952787664210733347407752179598132164200*z1*z2+49648691485194163447901429318606711262580140985559079028645914912154186791994327531361534734109810407846572283959898892*z2*z3-33915761064230038852198097447544091914852624394271815002883892684800593175107116459779629330687898698193211359275688996*z2*z4+9977744142959599155282733610695314433858871982974244792276171923772924843045082842624099463955480906126098792080035498*z1*z5+8646299739072312611568608239847490098029120938718127487494970197996028846040616862248455675569230323886804615367362648*z3*z5+4799278084075947090006686264706399916688385117120519338648995697835086573553112113456504237549644768716475515147187025*z4*z5+14555837561257397499580755975194767588563787290028757936109480617713562758066746973603513317210516778586363155217418398*z1*z6-19823132765313705549562914669003010489022332828532430197777178186972814636907479991218611634990183153523340108402759998*z3*z6+18506056989768176858819342082137858088387276582500991014644525484337526492341301396313228973421708986585697525821853598*z4*z6+60443302064054767834139671137273922614460050225983940837227107451576801734983820133953824794588963356193610680266041600*z1*z9-323029883909229868945322776566959936160245809345571529047091621805082367392374802380741663288838760615428243147301250800*z3*z9+246291982656556389565831216554043000109589862507170840457782611102329070115035135279311577809222296221700466859783106000*z4*z9+20136529836393558409997512525716258548735819698283112548971592217474247969743452701374931515542891446024787736050030682750*z1*z10-29360964852175134095689809314935859615235993810847688480828518599899479597635617177120348483977902993914225178223287496500*z3*z10-18550805226045911033470764628870498552965949448179657135795092441443720027854962254906048066149340712721580767158212857350*z4*z10+42192831637465208194535623471216330768311989845915195241692015083504135298652589102447536753178374618262034823563564275*z1-40185966234349689088106126979784693211968815282272653714352464168730423574002962433350168023929077427359307447651982208*z3-47005498744653096676639778075131863860005781421220962278745556067862028664848584716486199127502126761309276342943869171*z4, 4323178184097197752528153059818834378468972888902409966907247019858741072774101639965224113190476834115373574186003160708033884171324863153344267071337171870703134745273975209420*z4^2*z9-4965510890248574792997578798081830474948167535992752908425091156031652896376264573707190583320909347489909053160517712633541249283540094536459635530740733393160012129989153901341571700*z5*z10^2-10746284006477754661538274109924518272897222401454381470774200418292159224712207090638201521512543945832709079122309941516330040795139992106220433775005533079587593621406007084801651200*z6*z10^2+246192184993767279389377722961199553779868820276486976404330694886893551397363559532115756528736339415129782021831544804463198891981549800494569299864872058042540100447418572123386545000*z9*z10^2-30700979177959786740141522223546945437493945736880769838407744623461806985023825581996016045541014104303406517743118577302952880724825126455874698640618376425416473319554262853338454859375*z10^3-4211307383081498942283271144054494959127056455384713680971726455556791243647591808577888203057265174122756805505565915163046501898005823299145603729076351540392810313969246300848*z2^2+4747155366939846772722543635824532855091380718108858402142237369538657340015401884593913386122309437224853687824969991025967727084700366102279863991769013989110707712344658796190*z4^2+10010318696050321106246175251483260204389022511722297235201670557120537180312279814988571166132736850767292962690213598553673203029399546755861401934091502148160267833865119087248*z2*z5+5106744138642805370675438660601077298143781282690142607626446155528647684921412253867191268029414997366484802995331881026685782795550845927858396372544014715019389357093288839910*z5^2-13533388458566128356178066862226546387529130624538629304927288479987638852241130883431415660959977094747228255020271315264965877712682053764946005998536723772936797650622361001984*z2*z6-5555569186859169967746429144713587102276123013865896384900683127380621179418979936749818272980955221631831126219664202987533827528724468066071660609995332354844287234466099144704*z5*z6-6244518226523267125026017278271204285675808445148159488285785926042747022684421965683008610058982417835539203990430570536976859553592350374017133026581029872029490696302474521246*z6^2-40935314525619962296151184435070973477363187731981423096057806228164242004744676627445210720440930588956503166000261586685412097705369613414754212868682594783840677352096491047808*z2*z9-37656174294512205963172573428771496691341990364338926857547976092919198438857640919737216794012085406251228860596293022027094412715824951482368621876900161221418156568497466741568*z5*z9-50824907924048270264600067846129941959063749621255385342081537248086775346906767911531843031668413697867771797287549541940209627850840152448283505900295246950142404602438095046592*z6*z9-984868018240715854205704382535047465648087239462440007253273457032875821204140016026023884688873399956476672926192825918689928924905781258805697548534587480994117072117760000*z9^2+219001507339341825403459942373652934294824842075821053281500557582012635815109746939767414406053354488746417812581401505570420590533964874889573186200012149864969007704257346780319968*z2*z10-25009722212011391039778076695810112009178003916826888239789949202686630274195541152318233160233330303505022575150581241500378239624757927055317469722674407802216148636693587083454704*z5*z10-163930378199466578731143556712851565642422649010126799474481537293291236044087667613762031770560801710306188228747554300271213819676948479073138485516097132063476697661399468044908736*z6*z10+2417445300892819155874451480739489116312593398707920872104371311333390224657089777529181496141152654722327547494604733050972534248490397107835510782291961872113189350547524905632615400*z9*z10-290032383382310420034366053976174778411861055484219182145198219355469915258401025698183353945524843412948349470038411641555819731844941261051159148657946345626625050477518803904900733875*z10^2+951780892869240550130016422781783402627313651656641076358872239654335529875706320811568111008755451817985172699325399090402601242192134337434063911880271462313087794528128518333600*z2-20634840045983836902299348876708157225692914890606735226493110098579466251015024926848784996964096950199192037537512583490615524767053159654199870629864786223603386063254218075484*z5-503125775067157436940230679517105061209147397794163552796792046897845376670507556419702684163950052412310223765256560084313273761717289883351927239022922162747628641998702987716480*z6+6806630168552256089935451046478105818083482253413853566490486126037404188078293432483168830101234539098179043567011345393000733258552124805245298192914338303096515889345057657722316*z9-238657112243499280135167665484576916546715297664541984214067177998615666451925543342754032906048489659480168021363149875294558517136529461090396435398131066819753935313269011911175965*z10+2977564059903506827424834633329791373207280582414476922995804888556865475089117191598750456078429864951790155517231376617137549350639292913352069438534763546694445547722856842129549, 3222747345459720781243723127918030407676626100775405000986763778389469658117917887838064977960950629732430544582963200*z2*z4*z9+98645281926638654716589619882151134974459277403528698573383305984295448081312450673243885714634139430464472406218773644025*z4*z5*z10-12320479270007233037759376702629516016529501310074049673476800138866625840975207911896399269991304063441583334762292818400*z1*z6*z10-14702816118605125378375913490040429077326492686016739045049070821054358044829630869027878995175483131714935640312654793900*z3*z6*z10+80515877621321258514975632442588428219140304698005688847826177085932292183906090959366820689357442887243777082173034226850*z4*z6*z10+302964363715910512184538008436498387213131948494758717055660779547199386463780451677028382337907067307973125355787517040000*z1*z9*z10-961673284068881597741727163339959735626469015355250277884933890915276982897626939273405369774640249009217818771782253377200*z3*z9*z10+663108121799661404663316475912784546674021000272122032119372530787704113599955802756968450075440464720892159053637666390000*z4*z9*z10+10939272869061046988944635324195165373550073851228865134450227783497344514155483917469861470189295963488255644239372830078125*z1*z10^2-26153928309141800444416732422764348396343498019573089141527275326117645330605983831072844026792828218571079657521516709062500*z3*z10^2-55330889317080783877016411952618488870244327506968481107995061728691909074505198659864057134298137719160899467673899661423125*z4*z10^2-247451259313880808854849435845421341866835853879350060936817313709861357627680690910019423348341676397005139559331975400*z1*z2+941280880497245212659024965860675282885933187332130609779826226173491677860118032913293084542882164971805594347177553364*z2*z3-659655305072786226482096849486446146137780134350818826274705186861405751750312991879064189459114772561190010145927892332*z2*z4+195768187822431367378496745134287937492454088908636316498932942202678818083104852263656943698400920889209196745404178366*z1*z5+172551026458189436720334375535118294925519928511377699879880045043584505095051990480024305516119314898376016371356900616*z3*z5+67423677937061279020258001200384060289020874953409269383796508813241974034455752936346397875330148529206165523848102675*z4*z5+226387241925170411823790346478441189486914625667391915408489701548175741026383092096854264090746046487063095541499444866*z1*z6-405335214399071942132561308582912466743295186882043838527948822957271599803133425039079730771497767762943131797744175266*z3*z6+406456358709938103242899907001322692129477343239059090780787398080797484797972330958881446301058160347156576767069140866*z4*z6+1025752734152575409103542802158111049929451344279085870917495700945535822320721587531099737843080858374338369533381056000*z1*z9-3996211336217040566580475992067772080703558416933236704160995464527417221546295330823365968154798584884412902688527350000*z3*z9+2990093629979977010523085092179964392197091561531537548896244140277424211569545186354518485009366156138033938673198190000*z4*z9+165455170870593756842079001886200683254050519587697419704999135130476194032602522477131972933322594302632481622580316244850*z1*z10-476679813961668008273826858925267475344773054039404745107924140931355877136809110206484750230309559771575931343179041651100*z3*z10-146658998375956856158616742972918503457249504996973844406448058232056149248954721101130342146461304444255130569411997056450*z4*z10+421711337730810875672569588494602882134253716260045176238381451065940298325487023620249478162666135171013988999003553525*z1-488580013588481408150591856377607650064695304988588676109436890923331480128776833696227898968047898076480155126076738836*z3-606432974556132593145658837764046176234134731494956944562504987910001731670452873297188353345584024961975493736964178657*z4, 8853868921031060997177657466508972807104456476472135612226041896670701717041360158648778983814096556268285079932934473130053394782873319738049058962098527991200019958321101228892160*z1*z4*z9-26114751859269617773447607779871850558019074478839443201949159184611524085089900321336626093869757394895898661288749484559522986575450171665519302686892785058558290500919589774821760533200*z5*z10^2-57102525340427030415595137656987774740148446703725696702671328118401826299146822414966676895463562890948897220869990027272304183908392172623290217940535173789484440724509047357117844970450*z6*z10^2-836651162046407336431931379738440746025460435455489868144480933629819941606225800448240262163592856993185420894586842339200464041497889664776992016166789502660981407814751246588678444305000*z9*z10^2-28355847131582265497901971217098059053181895717605676613887289800928867125995879276775664774007674438855523508309691169823569391582235430251125904078500620067285072847907631454391354129453125*z10^3-39552638544310084654322993812784357810550152921217536607586117110587047198533775376878086472778731999229234186037176852866232679611149808326327480509874719729146719352051310276774448*z2^2+553366807564441312323603591656810800444028529779508475764127618541918857315085009915548686488381034766767817495808404570628337173929582483628066185131157999450001247395068826805760*z1*z4+76062779383400491140658729486220206204462215259081329341532778705437554029270027721953828559140278199659378107868347840722237678698568583106748110331868461258546438066375954440395310*z4^2+135509362085912954196884722182877077826299055041847048696629773466874681917374068549301743205934126665147744752636280490487533135169396748618957134114488086905508633369017629743178888*z2*z5+79984057213894324252699219205715406845859144749575725333101335976500447889319859285500298466992220147385700700095722850523117857669223090858593295852362161993918826931534472707619430*z5^2-172709575641555002495378633043336775284044708697263051458564636607537098983287690590911355509464588407006391766755435094081265993414018365942395973919616247107745494014952960703985664*z2*z6-68482721839124312573229004702475128996892694511292972326056184008851364234162209790611418950002484149421973949801414704791217229554104397095562988210446060533674389096457703938551264*z5*z6-85540202523779179034543348659374732276925849474259313090446774601988885768996457906014157168688229676504778980034481630231639253780567883612921935619698366594550018467270809366064046*z6^2-320991048457771410522473534462234684649242798614782972764097896764068562574516455782840083717964662188624654283387050278658515567946699281177833253866890310489391108995361971358802688*z2*z9-281856348788573292644592254958817370158318232051461879985184887045815829426853680944476888671851186195614398512014655238200534603316582199111606865902149792832356433238501876826051968*z5*z9-580587052272826916216718745593342111846163955279181976079821420319896601777603388967563017512205530247369447721511538661139075678224846942097302972376618654914409328857595729990673792*z6*z9-9473263263777113705239226713030170837834956532494449871227845631958470192663377847611196925697909990805767831241880604037807257209473719563367331430940847713643225324781813760000*z9^2+1291966758496451799583334862129200862003781873709503839970203722389188359711298862659916971953980703563818800310493719405608652623676884955905148376040655811114539942877159292159915271168*z2*z10-112490215822809481273762064609105781245458497798078232993819685888104922770608513207023150472071776116241327019465400631989267288551632081187646919818533317113270123364612869111802116804*z5*z10-898588043308476770537501105798319287911087937881397709632822570492359952102902793482163785174116019470680113446304449526727792487679914970196718445390075227479110798738988995798089312816*z6*z10-8486255526117517390862124982512362055150478776283231972690292280363117107702903687666900708711536033718877558529521283131456823367778181265267467799770601412272185476422190693145939707600*z9*z10+1268308204514113895077464394912187000085121363260931743239496365574274257658592085555590630916821247700813349381705529196731239314249344471265477907855339656756311595237524953532112563729000*z10^2+5589548887943088962241611544802348059553444668634867671436524885650018348612344923125203261897121925232690077653982187240598283043833959355978265246370252750707848154428564277208798240*z2-55265528484130119408723658359994597289704262568923015895914433036603315200464027394593754782941751243004205401876749933483111743452359458933120208576144529957374054616082070505594604*z5-2769628479680717488655891466353104725091855305482073260275012980176634896076037312878449949006715514737406971390446033300235802494274694859959866106274858223863129212520960798488726990*z6-19606483554937980840336596639520377333354811173713975624073783009368790351620378483078548146108555378914954067603489947283089489552581799028720867870259537257481853197284729356582071784*z9+20750074229717964444118412576576519684296516051674243346579918012023985503437551478276321234841771338755632955233386849276056732621529073481422036787906359219861070638273020301462308465355*z10+81494727406854788914471056510518420779390202782901622213476160088501958564047357057112777883244562621000382011104940364598658562329450811805067735119477710989039363821089879845840330604, 92078495584563450892677803654800868790760745736440142885336107953984847374797653938230427941741446563783729845227520*z2*z3*z9+2804455631212723082677487103124271952671229529950397689187816520168011751056637860815789223332102984964104047889897365475*z4*z5*z10-347575072648456011671364024752772671215137186623339034044313519011215461262613286145456390801836488587200566355463831200*z1*z6*z10-415449537647570900592488862064694533095934478476661084291179863211827301637636003210835626130185488686461379387852457380*z3*z6*z10+2285987040144976561591767135110461912361575614603074801060890188333107819184762927371866134410523159494477223164466755670*z4*z6*z10+8581248180627542884462549727055588709026260369217693714390521671844085064787880498814328754392495024115503197430085072000*z1*z9*z10-27413102140394114843635063073666022355377265310663753974171069857532304464231507457717147895442399725003058999002437116560*z3*z9*z10+18960810516106410245410751642514881641695614563509378294768110562020718878562262393345523832496214566154089968111337170000*z4*z9*z10+318594216678690813931653930053015754712056840195997217651246520472408964076965256879501634423865863941608746834746300609375*z1*z10^2-749658660433135990439779517976322066516522754617973504215584702297741405123079091599777101810817816983552770518932106687500*z3*z10^2-1576782418260469093372085553906913168691777245849506653728528206031208392931702051096257888293670474782908016425805508524375*z4*z10^2-7037602066068884396754450670100870272445162653355519439914304370593944988647040126264077241164316757147062038678549880*z1*z2+26764739678529236304894686390098106338645621988905670919735468838041295791922499202125097817691747608905439665611341276*z2*z3-18753191657928230080997644753627506868253785638432151265662348802068246359666583012668364957634076469858583033090274788*z2*z4+5564354604870591109201292179207847011540983998820438818275621665085665563507683250762760681878365761090911455456465354*z1*z5+4903313737818412288587544173968984839748192123451708589611587759701808553711886148447330931856367870408077836312975064*z3*z5+1920380399450898885741711240774668506411603557752060413395718396300932498136256911604431775710332603450012353597529825*z4*z5+6454995679858064856082555539819995183835231196811809346022090723896471309537857273764926885015508573696099096152862454*z1*z6-11511163404739522517234207180006272112909506917518475761092972548914740353653004983976814583633959981169289535544972374*z3*z6+11532557708402805354272207487223273170008043514464324781203434341987841113479289926904024373118381609619203834855248374*z4*z6+29019076006401926370383266204610980042908691381789408381749733327518979302827891482983222751615546580840322510589678080*z1*z9-113946727972278735852822385577365678554546985697438988832170158186368308718014920182247795618622298573459699252366493520*z3*z9+85503217572717500392302378120206445920581369198073422143674357845386806661580611036848976951769007425392702459563241360*z4*z9+4758576894582519378579067057423316132170750821311659483559964084734307953394942403575513416346795683948098964903424980550*z1*z10-13617253850855619680299957859917924443187234335853406785565135169187084215324090143381308487416294465907065913459205745140*z3*z10-4184061864746522645421756371408975523415581201970509033658485590339788441326016936291506221554635640350365321972914321590*z4*z10+12063726649771439715547493950299916355079299134336079874877026669754129004721620093611223434299656858440500890322015735*z1-14067380745626519537470103335950658416042701210091685920183524745609835860108719523038254634958099678061234183078151324*z3-17206290497415716652321842321832064746652190379487647025115265944313258723689162345061394890663161548930017109189130843*z4, 553366807564441312323603591656810800444028529779508475764127618541918857315085009915548686488381034766767817495808404570628337173929582483628066185131157999450001247395068826805760*z1*z3*z9-1885257393895088723591247484279177756135818248189984620792003677174891969423044206987091420910880976021870253046786892220587248927365174041108556978423462547765871459564396708301776744100*z5*z10^2-4589446970529685064533263532615077222915594127029173318030019456119102289065372354000278261759296355259862654271254574538310347526616392874983450174718228935422295926027937316433901027600*z6*z10^2-48707249497919794081795701810758196499177018492675103337392450162620450299887896190260433796688993384034736039266646060931284440681594073362020363361195431617465737854920105345288743996250*z9*z10^2-6980288074285019062941943283902030210409403560029171627511858124309110099121623895868458823621198365759734362878246931288733686334605402849540034564990333447045828136359925774002159824265625*z10^3-2381486093074727334718737695073670187309958882605455231342906675051813020612244142364199147988623780810712634456064267039473141366634444289787557769182728954649655366604444979350784*z2^2+34585425472777582020225224478550675027751783111219279735257976158869928582192813119721792905523814672922988593488025285664271073370598905226754136570697374965625077962191801675360*z1*z3+4582596372837198610660036106131652048053443351694317590259633145754757405241376505816341880287187539417446100752401647044052547612283073518566983989743615138366817542034698259014250*z4^2+8743119866453009924016035215431998377392519749579734356801088872397942602802044084844661928001136819481723900030080825941563513195981827554216219042943365287436552678738699849682864*z2*z5+4826824030252791263502375769288891689841511010809652443886012238656485450227813398799231545542126093221047840296900321516586644893723945815158568062844344497259856638546715467542930*z5^2-11222677976004531493170377000937515192731456677973307282031162803164703484314399473964247097513860821129054132004866885810692302848138242790687354229945660064211427060317391273162752*z2*z6-4498123065874002810903545285281313873502535787074337888449548685685993180153711927756592153019411821405393235014837618832735330677666352570480084808907646065618875230002526732468992*z5*z6-5282136871869366115538740162834409688183422306930518622921261456951994028771681548093211525073070849150153588988507964565258904311578095978401928779183995525025475386886243069174378*z6^2-22112569076060244714841262198329812934376084597948568233528589295707527771020068266327043024611381837203754632088368030608290473676193680877399507830796475736772229744068127133660864*z2*z9-18503536974583185866381151325544341714363076262595515515001328079561315465166279943190885414221674676478172358576475378170287652070937996107203703075203369562083687375667516182862944*z5*z9-41596400218711735789335950225477610602850187472329993296614393387387343548505115843045601030592887240626585846572250831979593751880712067977905299270497062428939437027749763838924896*z6*z9-660544688977896813700353301725844579772990062160924952061093777835430431021363934203011284624331685400938691552888928736744622663198114084279239935249309574134925161609850880000*z9^2+102366427243394408187152307708954297618180770253868966701470144177652716912408249135410714656040560898331651659130931087795713063626662550700604383094628700949600963801029233801622781984*z2*z10-7230487586677827798296187897996981912989436412151031501194697876194441260385290358897939781217190962912784095610054005577724070906932871375395264775510733652227517251557024139553395192*z5*z10-71603969151592236168686675770799994057408147700601003763877659014362504015493504775422697687773178857121792344843103777769510859733411023680063023980180272840271485118915584390045502208*z6*z10-535175751523233253931385387222569357494112777466980484335084728847583801767523303066110623286163018610322435158451631120339755500767507990439036334701632068023628508451580247270265269300*z9*z10+9160923263870098797133420578735343024305639201930995193619326570445528837187183496157408595116152227475144978202258104283224563254762335900465524530853421219046491243505747806104720065875*z10^2+445512075422838460455919229716915725233203536765990664545020200451152862250282744391714442484178981350221458515043895160167499321690736208045508075743359067564382931315071692751627040*z2+361187787693843952527706220760036710993202716251648146365880068315630515555563092183081823467542622807170724650596829988317665599669892600686732241202341544290651110628378154854188*z5-221175115111980700545484757884073583856550293632467015991825073407969625790944974490026677662814771097085092872370937113473048345433962613242629411231776209844624379355784307366181120*z6-1319811353838525021232567489365323198798291293646623668865082509506642563004563859086373669211894772247470811925143431516713337803070985518463337879408595480699239727067865055501387322*z9+968104375762291432220841241139837528625485958703966333542662607494390910597700168003170553263129585765541588804395878623493759497851826500478562148615141136345758928223713116429523983205*z10+4517487028087855642295997820073688849545438720617535962129789734723692252282573748286649752563554176135482472571789491761778032086554706726581069236850288898020662674460082338888583227, 34585425472777582020225224478550675027751783111219279735257976158869928582192813119721792905523814672922988593488025285664271073370598905226754136570697374965625077962191801675360*z2^2*z9-1130201573489923745978910084821118490145308536942747293213955322451539644844687362483942276524810647177783946663518634249736700124336671532896898606153761798884978677669776463325494700*z5*z10^2-2399430367901723954785083816963830801775902416086011891703296023009466172625975110230483934816702288964869993179328101934782461669030698512339384642883748388217657543866189434444658700*z6*z10^2+44607007991030831363575528218742891390969983185983744597766032780352826526836467791995500217176750139713072743174119596110328037851397767242293770133517374301467089833701251792511795000*z9*z10^2-5888275014748354238244317416119208755453476439462842788332531534680318855227667026823152703129378541954828032302146092330050935609594092952280601872391878667457918821595611469779087390625*z10^3-572469262632618508327694355365915887115530024375032379030696214387399618646437900498087811557385531773467733459415232640316147985389883315435755324039510250629566207385247652448*z2^2+1404367384106549202984617056164937942153949974957471064676747257956516529546030497722473005146854818788933105084212501548209441942417694735830999938480396153118592294413739057930*z4^2+2625890319350936123363722018183297854935813654175384661130815164466327680516805168540643524992388551313248205729460653280433396491323810706871160826531202909833864566182232121728*z2*z5+1454703488345963018362698063532534904303677826983188236469919179440105520260037937834101938797009457596704191987752152606106730200243567866791528767235753306170140531434418645330*z5^2-3660647209262826829323636308568883123435178795253974144594785552639337268078868027148654046656741008726176532751465492224677267314315350500071202451287932311712089911038530678784*z2*z6-1489642462433005471325970197893464520674809195729064057918103570041245520097037994333962119118922764566641250878429410378355473722661416692728815427076180260990609606998608358464*z5*z6-1750176095805638290293023779256645278709951259160757195720877613758393454058184334273794772509160773269042039440947480217752010645324815937885950971299908075140788061671665125386*z6^2-8032185689150339431907891516104132838569977386860987412666134940083713134674743818527727404197451091441545934429525204539323832289225734040747435589903993016987452602282315009088*z2*z9-5188176842617109703758851712099889636935888593648048916376917870338297816422719393047586693403896357928902893001618956280830581132981260817281473753377704946710641815218612685088*z5*z9-10661337906891061718060819993820164225101817541654377770782483513082833922323072788133232799676058860145426323669631052461262956821446693069214207829751171435016549440392899902752*z6*z9-182496742560873535880157252567082174645421718238100023718107443720720257646069461620814640182259177285450130456409269727222689298281738585986390036465259868593020177960960000*z9^2+51616762404552435186092067750319560962242987853351197559356178759315224283787998458460833634328324338614441183095408868315004197963630805800186539520145630596564897958347327234555808*z2*z10-5253410144382898595857239553677467644423155080262669198723809821757172357402380409453296515638763590826059615242828258840185543413644953402354199483293811112945336829618303454994864*z5*z10-36932256986053352958540546695209784832437280700045675699054381569241477116245399814580630266265236938866096792377083802074000695876346399668489929217634865755557300606722392654668496*z6*z10+346244316435290464856641999095259906015705517677959406479967077043348282217368063550990247459865842143025598051850006464257957624136937236075523468994247550495794130994751282825484400*z9*z10-45265701820840188593493164871002598392942954922561956425025443151895082225767861703363997669290994766831993802190564972414349062136990834825423214035887551502394207286403389497229690875*z10^2+225443839131648241507526500950703230002503632265733372798602543624951683023083296685238994832070334309682440462735828052390781540872327765867891383564365004445075103236543286289120*z2-2696721561113751625037917428263075540255538897108934838679661584820676494718339650406787030905493376229938870510551577143047124958554855570941024037475890440806830671913674510964*z5-113921780300759561330270113294127585859189891463007231048605852976625960627962604525630027224602145827604397031843239578554970270287462753889196894259603290226017042839073848640820*z6+649726698505001900461921900214931105503134103792375069295202637385520093649425469933594666161206453986845341496697692897204154020822372679187890912163692884560319750699590113225496*z9+96578625200849554521342628489901176085546173316623302146293354684213398769330225872853189310129460319516163630549227197808071603326155889565339399525234718344726922899992876887544145*z10+1108229327326884805422947357330015728896400053994855449749344647470360814726555594826557447048512720870376641802802278288937663533343876290696442891072261519055657650869574313753309, 1074249115153240260414574375972676802558875366925135000328921259463156552705972629279354992653650209910810181527654400*z1*z2*z9+32521181431532391528778630584871401273497329352912617232802378408137400827034214518537952229186839317015342905591369275875*z4*z5*z10-4034069551004041038665506522501031877066429586841123482563496977808603654416907529535682391675334655968109033244103472800*z1*z6*z10-4820205695865288578613796765373654962598695798977899815704601577959818263568835592334910661620750581955556830116081992100*z3*z6*z10+26513312593410804138864457700587258929476701232942497540420549364164706316887631539465515826878079308099759942847048961750*z4*z6*z10+99613627513226390048770760327245319228378940458128890813218618682419906876747853985099014162274391785585282283357296080000*z1*z9*z10-317863988560893494854968824929417713290107917338444360011475214921245011922933131464951800293970385540018198142809554490000*z3*z9*z10+219741480849457677258502486182934946822101362619790618508095481776678547701921121478058729779745769402083923427970428370000*z4*z9*z10+3683023512772499229083076739171578814322298184587496205440502624975473784420632616140711325352180505389291390497090334609375*z1*z10^2-8675873006809478389551357440616538315399608799620751914361852915260333194662927709944484365126753330875228043316164804687500*z3*z10^2-18279315886124581359577847786209411979451103485352914955815546570578775691649004062919445590724110004687704516142380938124375*z4*z10^2-81609740187367765345154289974201944936061678847094541846175353055927812081214259405671424472460579875066159399408532600*z1*z2+310366694887768860994022290222084351686067382234085682244382867111935398411615182146824388480021831937998528185684805852*z2*z3-217464948731219298051171746717361790202851820123586583180560088615050593430025356827489044864886484602148850745419119076*z2*z4+64524866272959202341185358025109507467542694408885756393523367221159218469163832809971259310185722295706135075287656138*z1*z5+56863482255264518988165262903557989796740202751354943543017222015364753961290292463934987787973167636518387415199792088*z3*z5+22266896812028643135735792762463170415703784363405958406643779869639972158901990769356588074860570226150851375753817825*z4*z5+74830673166119156815848069786043142937391270017073826262152130076404643510240292469797185809106229637763966466735115638*z1*z6-133496916615461931654077215205288425751539369962365016914391715195168624821591686477569954911846998044007008840281025238*z3*z6+133765656888850927583128900867608872692446354081271638081921894210728857490176966204355996622409948800775545240343736438*z4*z6+336145082168776562032922637503451898918337946287457857768685551268553094376995051353334492034501008172861824316229132800*z1*z9-1320407191805525784307005797237910983567872165331964767211522864651254216335594333074633223891296081798240930173678514000*z3*z9+990917362066536397835592059453659236181926994730779397580715722843756704586746391592948351613831486488492227423638106000*z4*z9+55100116703792806680115325180870993865126497100108626987773508245334314658981105357906629732751759269487439746771492314950*z1*z10-157709716693281866683366509507550942302149394179889135606803071400867310053883846238962641006447028693522651427279989914100*z3*z10-48530924573746339336063606684932757442922357619384515478130162310412950901843033568984837166134962612908178139952985120950*z4*z10+139783263356337180059705742525596591922206908567049996983583411111604199039049984443977762817670145265844064808114253175*z1-162573492917970935142673854238943886938722329385809068565884555446460984009024687766262699163833139511203723213403198748*z3-199734078848499429709718447253793439764666870619803614959958132863913555423403971395604440209237006195856259026187913051*z4, 573730706082812752617112203829781437900368779675394387672247514904261471264280138280440878151153456846184873179654153858827459981930191119025579020743984613829761293299207359632211968*z6^3-36476126307402008302553547162182934424805802743786868099167524392689570668663276190421525880494208902401551375641568681256865955049564689640043284404238695153732385887238835015220551270931200*z5*z10^2-85778667532160262546201701783290096013961559400540574297773180180613818407957246772018126543709377479898796812764884490814811846599099994182125242770286173152438190589727477903572249883294050*z6*z10^2+1567338445802898023003509799566633694292843197225713420993607999715082543719109885985196065088634096510194016197739046959868164411813996427953416066900913073640628254717357668753700690642735000*z9*z10^2-593339140898850854137404627066283523678618035096271163017588514477875161088009624199838783388493167713526426352937575974773258840542021450100734930245188264131419694384140603904120506522334384375*z10^3-141540194334477051132847834511604422476391942935405679485147580045896327550501331765252091914104660621855568662315974235618618308673739293938970558579912889826189630495085255929344991568*z2^2-74625922229903305791131754273252711453396846845722664918625989036721357670363554814466671866020495352679299193433056188005019730821093103381478546659222547055655630338784928636722171046*z4^2-23057079522788044689254846090300609659970446461443713691135897444306044025532294993491569062342462675356509648143840166622037791468193519764819092836329436763121542128609613128029038904*z2*z5-73230898280349737909210175830303071140682551339492562587093640291343937644461506262715533197609344383023318329234255272333716997792751342123483693555886367883167423258245879955867313470*z5^2+128584078668833948586473298380036472156626914093692340293845671027099486486378600958621087813211483591884763619882149840570732888263159335344938316417810839256971658666695470522361156608*z2*z6+5668950484287142894870609429273139925991065393765302198631342221401774806472898323549155786081448303158224770290976628276204398645949669548377740081954275348436248720773725245182118176*z5*z6+11254887955164207617453154078816585175478409574046221973614381819064387611982393863227550609970436430477247954166942505961043603598169543731234385734169609698227426857622048394937844006*z6^2-106664845563189021859734932147876378813153665835480961990946232421548971767046670291529621754002363837229404536915272080125775829506948241838412718889532643325358962243392885115225508608*z2*z9-94206251905155800446390274785216988152975787047416135239832821087464753083318731992702998374715662979751382263171909583128182296801409697365607534680434099443717765410500703840657033600*z5*z9-191093464247502374145730156650801322890021294555911491304428445700263717095267927562874967472346185538021441510830067551727662480128477927777882239131620637330173644452185884012193913216*z6*z9-3104489598781266998134289800679082464719211210825113022662651712492265137163060164625017411285084543525981627605460402818847258786349202531051524679835966427455257554858783129600000*z9^2+1410432309225620427496196689459892619515075479420171281056325393648294499349901140740567277638187961944028894147168679855323238853866348721499573599244001283860919152626097480235598921436576*z2*z10-202391890672869895067836552169019746547109747233543360436706167310205321463183114978373280236897621360311985794576077848230391714510212787679368587543136789233919883026994021964883492499676*z5*z10-1191849267981480858519818172672652199950701680571732614011051110510187294975848285917923731965517736499258410273307250436106352855345144063166067893626685433863693414007358784919600461386712*z6*z10+13596757507670891932375130999190385838746156321651512617715651980777758038407099048309247136434241399881583462878108432398184834936238598873778869224597896061272614181278466525848636971614000*z9*z10-9257531533538694770003352274922098279495123911972369909043781305517457703210957192445091383666153925813074897509978101349933096824399759192634277893684281471310249073707684623466178058786384600*z10^2+6056320017983479625494956604680748834753443774644949533421267197052635757432409536523556921097136793798711032008277378697627638286044678535573637347119115699591892613309596258204646125312*z2-263744124358242853217947615967507997465196639342804475478277144066670682267673083629090712966388046443458173648541448593366466330229940364661873042645539933736965218498646900697015843780*z5-3437186185755697568297684256451226984226854617296265604976254989622090977236535318228564404147216271384244511152244017028211363782955249538665035307527827508307286119600175046477660993142*z6+29336896019261305639552710566195449020074310761918193116073491809275814254654021799271251808893426697709123906152536908014625378297619876930832206218342208820330952166146515889509856045592*z9-54270673738073964383684676683666725579612541990368919633960747454639028169319419272883915782427143572165040338941358336809365018967792787372409049489725305591393851140958984398444898812563367*z10-127560853380220542175562775556615452716131443873139860178463519951878584535663265566415310452721641972179267371898107631152907297782284548266559453822178057954347412076807102320926400072012, 717163382603515940771390254787226797375460974594242984590309393630326839080350172850551097688941821057731091474567692323534324977412738898781973775929980767287201616624009199540264960*z5*z6^2-49937606643322598234477242097420841648725447972436135737050598867834718189001324621074170130108813751001324256415613159666838454771354351034646130912365495030315785206360083043306875660345600*z5*z10^2-42321376464657826430398045665295352991427082789701252469817589748853568670581047700854691099365212825768672396837381787966674396232197999605603523816600629143896880885289251724540503929518350*z6*z10^2-917068153401068003923505782724617361199389230162816360505795613528973958189124258731853740209521957059312836433188999147498501859423764453880922600550315145629678565328746198758669970592615000*z9*z10^2+65313731028438327256392585187358432272038470607784441309033671063720512520870094572291196208493639641432724681243173560068994582422702795981223007879917623152652981315893955499691691849791859375*z10^3-273853569776509375586225539756152192703201562649743208702280855389835830451966660409009252585842100839706424934726280014993571792547283022593775409064198763591862066560685615494065665584*z2^2+70362567159152454647277814600528312039146889093325006712159477643010085938150662852099671884580515379334040174803148862707264571500449548044626025305094382798355389381926136992370995670*z4^2+157329756561011553831060521609909697579171473631047868802154026270628417074379534360364029121766522860144813267301269997966064786293230529240227994273846083980272474567713945082369576184*z2*z5+73858983242509133007109529411709016418761977643948995685987145845666238991819563106288715950764310677568712142331737041346361308832956317485074681455728854779393516796552214938631925550*z5^2-27876592648592199386551515568379006775362595654189237259759048529515139900700824469572799183980424161384518459092573227393964618692528929278345360791237402288139288488518358926876029952*z2*z6-78870253476448192745748636979622935385954200304901927489233876057333633148437924424201504199684750456833085590380862683772364382327545167694806255400069556312124229992701197799015303712*z5*z6-78092506308983242937354069671324974502498891775073696235098795665042509650853618452317117550459748455465183147400485389768659131488148330565270381067728396537460584044204042507987735638*z6^2-312938030088381260067632486060475837983608801043200357417713881667451709116208430374904423921592047134714290700372917422005305008634581565591268305491099258790180497434872852112491732224*z2*z9-284083900838739894317599496662461213697943165587142306380199920170046526416151911320419324308827248168977939274668490437973730296360498770566057079121671633815160922368991419094249704064*z5*z9-575093551135277296055982566900841872598586324169062836863370590381736756241050927724475421513491388791089842395808270408379878982109416838357259873497266052070726329092305573086145264256*z6*z9-9344583696927577468919118091087841045167182865000505360475754932379279530247584725574080082000266098118150135277348430986437543589654645227799431833353887741527395922086961889280000*z9^2+1112939735892449217928518384383311214610909933478094809886700860460233945886944788660121166106892479608502497541870842116956946586906632800667890227775073638319181939604250200147300436524384*z2*z10-342166559774468399744459863091812490412496534078544009207395002675749645900415031501620686596635988294632618101909710422686708130247882703266479048019637772397932701582333191274766853092932*z5*z10-701011272417936491700449257881433274766241840154046672837743654739660120045894427447238265138679390815336979728321258247501958252927469816194152609070390383914663728779178418927472476188008*z6*z10-9257454011367668629907108386963723529484613399142727314268162102222484434910178292608578282278857555209473028949982608780935410056070216208554020861266336515523924307697677528524017866650800*z9*z10+2268339234826752298945879329680878533446045845700318372600783081125934153028870544586105282663556503475212025071546788766740571975950486126315044594294222024070465398354496343821048898110071000*z10^2+4484052148428661901114528583576990291057893725842355793147663850594699751300754179197365611692645462519618470694946251645812917477615233427048131387819362275960656116258453100833060394240*z2-543899231135389687758328635005753151913002615921536916839361499501902838541386864618810182445319625974978533610740233699122767477292193446154923434752219427218045823999246955512011720732*z5-2134258444869288634230713177227883107713007948307973269086696109438798987528432913201814207625216672619359769125281384577675722406304587733779234422855508425457519433528646967036359961690*z6-23431316631588060639650810350099777462791473774239973663038322080324180528428169182294644921702137151592094050475473075299095261436929930037722879840777836527296258465225467975259400493272*z9+23533068677111686070934931550475693388059853807703472248216533481706645966391223055342397652788042633003246603236081609680840229730498734054492827084151728618777885504639119902534229221766495*z10+80936204373294298416488466485723194373980074249960798992005150974213628579831285127640074572809343823359622673532694443148068876778938260884335245280962275856855341008026593744152434682092, 43507089163706230546790262226893410503634452360467967513321311008257840384591891485813877202472833501387812351870003200*z4*z6^2+1698415349233947234331858783649842005757340722144559938086556458512868019846386121097067402334817293746110835300980534724075*z4*z5*z10+165323209217189081586832830076375196573384053056562119135050436361307048389764781663142361470861933943530879246541496527600*z1*z6*z10+224257204915254596964415969026156655088197428045898391327956506005840155724038937519009273224554797820833254240703256879000*z3*z6*z10+1338529170267571931385133997761422638061650851027476319774039579990218333199614336836836036804353391702141693100910364670850*z4*z6*z10-937531169467662696400892725453015079402903364573163776405952874591955114844764170590279136064333138118355460156559931040000*z1*z9*z10-4257036131183417988901635035598769601321299589625694177992073761027508861449315044201978526367138044868560743734638377450400*z3*z9*z10+5244184236889631016566014385619184088182780405951986581195025096944231009131425164646206181549611779605420066880769440260000*z4*z9*z10+892425812991573601320165819631074645333814351277629866721390141992289649051544166589264601763206671664901950074787510985078125*z1*z10^2-1850217568888727059495386903427336675331404125566182100352360041132891394123811373079685918206053830965206004342656689761093750*z3*z10^2+1030910901307196506352166967976448163883913906639206117790360682193935854802906712142809352715317390752316192841159225450655625*z4*z10^2-5538240034521861303247351591723270325978119770828837183465571467686814284065538802828814041616026465127817203993957983000*z1*z2+11427747135056078815716502968726109701343360791251974469126579367074158418350574099777497447119415509315920774434020170644*z2*z3-5883942342600532478633660810767564979724543673634969588396570751215686384642031416818360042161329274236547144701535741372*z2*z4+3857627068289216677694751090692916620547467052602054636316599678236731118711887376663640712867263460889726967808043886236*z1*z5+3841591807558973419659459252483644480972630045267200589308503325902689241017930886276983297235810640106690861515672468786*z3*z5-28619538828561745193756375387448526573331852242860840384991129477204065623932837084784487975505533752173017319497211875*z4*z5+6961851564285052427363185943412501700865928874252284170968756425955666172044232033143776464874032333092009030863192146386*z1*z6-1100583115754089341114493617505494976112447553913176726288854799218988784670161528425070475592464075498882851860708147586*z3*z6+1709609842247864187986808627803465583743252225218498925568826788204608854056806287898836226290779174911177973523665076786*z4*z6-3500703251746822469593886785417238002162036617771891018841369406036923951781341730718644872404543606253991168593187308800*z1*z9-19904796016666964258162519563562350568280051320328043440273210605989495206385758661632798942442071175483321148586092042400*z3*z9+23626909287373268709827032678102308728750137677128297660865276563068740060536565771505327346960995303889318935880396042400*z4*z9+7212785358297946766862420169963238174211021005511305380513449684268682603332424593479001234896590746781496600752160226955850*z1*z10-15582267288072552634301604318155415290947727000922698128394108120968464945117791416765131187634561672176042100505484490682900*z3*z10+9981922021877095142925531277229838456452510706997596416888276198291696563855419527908217570813466433653371652246484954540950*z4*z10+11880236837157050062268987762999300962026653994716162920961711722368952906451456655564822539551847153291492336267657263725*z1-18769748171678532533662252491641804480863111164578069288982279846902040957067588903280798864362299050255518348664785219706*z3+12624408176014549532689299949723801228432355142028515581846679864446618841095470784817300655501986212982550256673267587353*z4, 339899134091454926146798923647604769559644159066155996197822742252014378004624152232920915644319011729592283998984400*z3*z6^2+3614261006790412324360187751079708524458805370602010838352090401351431757214889092793050647595210955859980111655668886100*z4*z5*z10-1233750776873476325881489273965248445762617804067744294085557249785382125389089827955119634257533238821914613489221849600*z1*z6*z10-1743283665662339299469939907779583022309004553625410496602699196256100384650262641938412820801271765757173582869155874000*z3*z6*z10+3786310230055532629210689790232863496915860118333752353626248533991757199203281647649978271866599232564111642852646271000*z4*z6*z10+45709619042776821100462679961512130285153414661483993807298972929886048261734091267109068574841740714093006799690495200000*z1*z9*z10-83481430147716639768920078829786167058707679951259875217833878245303664372618784361264530635581885534238751146494669029600*z3*z9*z10+38335897992134419880391220022403562046444618306204915394703891235415842434498817089127876170835580646816810905547388460000*z4*z9*z10-1399075224213348611291399729562047465753916824585167709574854894230623494839704668339908629318998615331236445416886457500000*z1*z10^2+2648009274179462240644533215138920857774839061374577864987106737482865273250488816848664814860941246718059391696138620859375*z3*z10^2-2123929847886049063194794854258928859130116298159263791290200682988776230136600927712671306628351410763080665194939403945000*z4*z10^2-9772729125455441969016700338411911955326571780899139412996633312579401071939266558957727294447570000599730308017103200*z1*z2+30557345048076122032053168949351472719799303117053074016644876215327133176669418358592568926593489358637148341076049008*z2*z3-19563250883169332162757559481444253277905388140770542786819031420741045003010458548233447815623356258457362120127842704*z2*z4+6615657323423558786197987437493104055633282652581361316452812539173088876495214558205201620669205291121765193864472752*z1*z5+6703520973136208076143197556936696914950203210473887114451500545881021750878084450146173830976964559518724579116249752*z3*z5+3436550236117715786970084244447339534727068036520246870549273657415594214864887036215730502066344751733879740393005900*z4*z5+2544170822057522672519549886299433896300579413123112962960755323484653302549849335256561776811150864430387785417942552*z1*z6-21819023837251022806934482811123932825766091443783928093346104428959231687562641120923681232268865486986025234331954552*z3*z6+21805039914002217230808031388096937633320633571876608548996037159433629112211440385470143713697698561390914081683273752*z4*z6+211692586477546536835162315586198463546115154090818622987973909661227249642841164413644077360333823745708714196966086400*z1*z9-383029789202535541887974914672981187716789186693337055171109602816711349012718279127057453361639199970673059124746828000*z3*z9+173854437157146648123498494837735977574392327909275499293783864890584023599973476687930743976036731707201406680404805600*z4*z9-4644369917562308811396456335984919991940034363698875073589184252568357880660412591451059159877801497470297024768114051600*z1*z10+23254994453853439775619927434920516735223434551760819625422810427893141479764311767334058451692014377638006483990605119150*z3*z10-16586545530037690554695090258456828476129770295716297423631573301900160906589717625169292780368576299630205339622803466800*z4*z10+9537729213446231976642614574882795803972371351914033933838592630050362263280710256591035565102701338867325479339304400*z1+95145753880683405591656820821848249276156014222710205611738320446943218257205130264770851763663450193868666153844959983*z3-79151173196258242546932353217981235825807292739368919495560011968842705698335473834272255717879663416562913207674732904*z4, 59763615216959661730949187898935566447955081216186915382525782802527236590029181070879258140745151754810924289547307693627860414784394908231831147994165063940600134718667433295022080*z2*z6^2+441185633693191332036062218087284463713389742977955679902059121455442253010928217839355514980000829600469373957365962956175332361693861034247740278792625609276983201157601349527698614527200*z5*z10^2-41696201156359433720355622217927064427944270495200796906984811378265161043141553930355896194726316806940803633435327319629862856115958567316381667121893073950206847087292097833585465346050*z6*z10^2+36651912539132316915516856532241204516198754346257137953807537005407968570109589961066026986550238804660314099415801371134002275260472551576944979431253610213854217417191871296003814052505000*z9*z10^2-8480073413385226125128391240610595906132340572708978189460213720721418476362300206098473318967877613764349932046946995366638615202869929068171224739553316998994092298669162295166168467510515625*z10^3+8426865914992618265569212925330718339506756144799921089580056530608627476106175194987812120311226922646862359808525211250813830272473866991156832067359971378121282992953092195352605168*z2^2-2419510438173438715776051582492502754333834991749449433484153009179953947327405410034086520689864442871215440721029229587552623591195636735690901238280244275858994937710821318976239690*z4^2-3011052651107613112451528894257879129772249523197136030890550710388854589371590216976102298607139110161027380505305501453981822046893756252990888726825300478908757430900873900059191448*z2*z5-2441313100758118360811204958488154665897194360640828279175918124385002828868909122726995135726460692210971680794271023685387849690853008367920312736918528107668034767029441541134989810*z5^2-1853764823928837985457570388003263554554475407575347375168553855285428847374416556952308962296489009469720521069389615671222351664797994255679045072939818156643132992172879079016239456*z2*z6+1486610240439288617345186257166242168353295305641541225847243920023809770700436320900049181037831909717910409626398928927117323250831583670630369448047549055139911669532946123879852704*z5*z6+2553712230175545297431003614876544648662649094530041085361315811911590049866563345731573504474283020504680439696732720140583556513358411419780637600183102737375258440531133915141471946*z6^2+4954198523705902112854347310948692048448958360385624836111892661726048999104281108320202631340452676187659238904332775076309592582248309211582684325176842585340006285726504928950021888*z2*z9+4607709577174661419748349820985382221289421787717038977025853514175972985398056958967981977584750901528905084946661892900221497140489240520556469541839585164002859298581444257608887168*z5*z9+9276983757052273763889324489108070394708336385727038480200469049550913554532477363327778863149877756593140360629409983534720495030535649992731358258964642570429368477003099019489254272*z6*z9+150771804823952067103982195880968449439262772736956852632499171265022692629893969691276253283644718156089390978650715326009053665988549245710624055519274982564876968818899599360000*z9^2-8878666608695476757205522807247117976999639105660645594489221677076943790020825142559692836373440413781259584834187371492521316020232518004422236833883303783981833829160476275776347264608*z2*z10+3426679615897358033154937033391748960756743545195001537809247754438237608543527997777626758639287081007177584348849408109686341640917406774026306424575356814770518015458887126505331771484*z5*z10+2364391930385650961202014772691985607466196217188538049870987013275854167051680836997205907226015858935788178699994189234138636943648292988572701633022679494043114471143658847168169953096*z6*z10+342803424623745127908988876328327806993699260019172794991731732574408466718956154143456043017421755691431683665488535050263620012939128001954407890114574659759147102518191422743109840139600*z9*z10-161090016084087615600425838444643536820996977520191261127216635075628659499684201012556608965614239240913738122556808525297080126988993282354616324876415537787106852461726611443321866624285750*z10^2-26796275404665351489124175610795410552710897794638755024344848382231433935210584518403523783252350459246875266285470029332030996610647834365993963312348790943262156923630275711281973120*z2+5774171598234915486624742039556541813514540334304960023472497357117100733497747551609008304076753218529783742750263679397193267461421901521202819505003083822834917763466962064533708124*z5+8184900838779155563375488409067239235500453172623631790400306642657755766699080774472247773833548967164918761403596205776398914880664411039726575450977274825783001154482494187351897770*z6+806070123357624734172915747988267761291529006789957263737593481309469405517031409620670405129587223011802027450434209973999481615279387308021836633418057974316151856000821979640711956264*z9-1172745166083158367691996735277049710894350507856151842981039364450031972380547951108223599633043867483858641723755269810304198642465677540117406680539443637249612947956977813296446011669365*z10-3313805099976214743123498929062409614984082055272526006863888876941413272030178993798111529751130956162857649471600336447446587359043484018893281491548631997991378239210898219281472318034, 43507089163706230546790262226893410503634452360467967513321311008257840384591891485813877202472833501387812351870003200*z1*z6^2+2738706994456773175419054164765115257098163989856597226145692037967874625884373731177162835664107448088439642417358016666375*z4*z5*z10+1713223095275040002922452579994204968841831309569317329316341420561224472424898684689211573286431575455367675890055940629200*z1*z6*z10+1053922915551051401725935142583278984283513815368839270418650985859231666403143510362277690482047953058427710267055335542200*z3*z6*z10+1142567023446683167555905527194339919052686075665277027985982449517961413814012692888580831194334191650260813962007913179850*z4*z6*z10-29564276451352027535087931792353328437650239500516938612547181362860046040635149606892221503555304177061967604605691124640000*z1*z9*z10+27245911664020884697912835925284744090903178244713134047634653022967554729857680621343960051224779978215965440395074406581600*z3*z9*z10+2271606091469116694845711272261789763840449534776591231064885701985116782794141998209805166924182708561125512565444962660000*z4*z9*z10+2379848601254743342715386836154795769317003085539441296554369692437629422860230943491241975784521789636429188602268707812890625*z1*z10^2-8141333337481956570519943671871076525821609761197595471803271758752849508530993412302146893632364094266244715994305468541718750*z3*z10^2+6864939991624899620038318249452409640009993975415640595171605646649678245188359038506681525634633846262907323295298170819348125*z4*z10^2-2707655833791224734706691707146331567999824889882582395257608829479834076524290963171740395647907233573255668611440875000*z1*z2+31914374853189683293392590386848804325898898558384357333786415764058887423381288203852889245523743632793584808891738470052*z2*z3-30378785183568039576573887110927209817200353524613387782087818252674398008635973707569417872632545902245424277198430724076*z2*z4+7278979758150907127986604956273579989230592609698562443598210737879838125790916523631037863030662760851467827905195389388*z1*z5+7665540787142059370086192504629656410451764020738448211207665243022106533486871524613763738930002854994275856444601552538*z3*z5-2586805239296949865832995229151989581151614000490813835489285917007287307268964823349971554225708245055539295209172807775*z4*z5+18392175789621087054494525448674720963365315387928130810263509532817470072726238521433379347948722303289935058842251653338*z1*z6-1034850244934542554579180868924118436150607372791704096471061633945676186125967829081638492691974391959402971927889697738*z3*z6+256462957187843349261324352824313886061270639650368595159052105218799209475706200652145245348694166828240999440751350138*z4*z6-132493275590212246030328104129110722139292239705076628609792199444537775624223784315924913337751820419878956220244156345600*z1*z9+122511266409612999922967147763591406916042067097353202213706045896664809230121366492810532198235551760135467365184014946400*z3*z9+9773301671785498078949383850240718194708726835319846582615586507736955441997810671120397889954953625944682713710954346400*z4*z9+12453550129621390202615076931043726157875117775513233544378166082021944102629427908512318536522260872769304664283197944974450*z1*z10-66508095317923388971419584774060205178817029071245964079384686288476214166214639418925308226077102027408182621246507062073700*z3*z10+63411779608968616490433401516765902996327228635960308719287806492746120169285142439568656015098987406080794753225141620817550*z4*z10-113914053309854450251717549788021048016898752004890028896848405452949583959287549115933912537993455964036884638955862975*z1-107956254275220483446507532883467740083381851455237569389240502799196816933386433029969576797716260086558173485082810885298*z3+128391959401793579283348942254143415610508031119213071271218557133146965347179459284378063445498742384282108899718924046349*z4, 2801419463294984143638243182762604677247894432008761658555896068868464215157617862697465225347428988506762076072530048138805956943018511323367085062226487372215631314937535935704160*z5^2*z6+329831499923789936552700209528880489897877047142811185303765958624743109456169097292984013710453471769432826847523028901163339862240524212403677860332196248727047452392801218360048913177050*z5*z10^2+544540428314037916865774685500781452897697903012625931993830471196065879066583412819869248260168354465195497027302422969503795841751624079956929618345451651131277747029995578399676753675550*z6*z10^2-2262819615521058439284135492270543205650117807929754451384832246373722305684993189698408262960425070931315209342020620126224486207314639403229061239927194489080377864506348323093405657967500*z9*z10^2+1831968940347927812367651090340671209646821195189100701664076858020900331045085625743448468589403839791657823166141796054718352904158811001706216243123883167789435019872340753330013518647062500*z10^3+98012060523905617658652597619274053937561984618363001307433033054354943764159560542212468088341676212540417067755763710093966406848457960538955658694209272678916973612887895898316512*z2^2-21175256873178037889078564470655002655935290025870135656634091281088565977349016128499057346221253764993933132819464510032034441507959875884187015802372047532185501863905633882539045*z4^2-376624825868386821184809093346907449466465847565852962855600861312859449955748939559003147490975695884280247855966243288316495323927410855107200727941642444173754645659199971332589592*z2*z5-39296375536120316989711209185544795003329555705369197607004729098162875569658667714120581250501288435592419225003557821134913387615879797377642081464601855330274061183464767525171505*z5^2+509679337943739682276190592579925451677456148613099551707810593266009499761072026412455290950576798034678791044790904492752164042737565773557416214133055798750224326426662649012189696*z2*z6+224123294843735259658487350323887768979463045312101980764419427675822353888369543773202234296354194949078248312879606249106995159355086506790857688887570613982526574324413403854358176*z5*z6+89039921219143824503592254166568347579879271878386143813525560553159304959234479773544161802995453145845139600273240688966442420438750449655356783659465177201582715210561371780540069*z6^2+1396782213612191058605927919116300930806014787054805166387416465703420312504857403856992455158553296343477118285393169029994245259830146085835906803422782904509000205273184800213378432*z2*z9+1388754893490200669954783138285702921683440125263893735970182642381840119221573197524917280536949794343436041499199363673579904071425637432177399956762627784636575780052213255594634432*z5*z9+2789373609526130997336253195660432603879917633260036392710313228278496379745261688620421182434568281109940336979096349361336903600865853091770860873465602683004878377927461442131813568*z6*z9+44755517378690781164821177893910388513354129198423122058680158166764484307072372161540203448260754124525608682746515673478458893709895333863497911459989648084231677185968496640000*z9^2-11701197388643051759841763714840093247616448209003454251092995963284534199142454585897052596994960108106041754528912977809867180595318862107524876385429998505005527616905641373200212753832*z2*z10+2136034449071570732647095708785244006257054622521227047368058109940098229028834677598343963082759506341875616554360923541108178199577194330848548506531618198707512821079186873708200144156*z5*z10+8389753332003319516857775595834745299287330789299883813681044090841964636691710277910025714645625752832758696294934168920584551846649681201976216470636325811105511737481608199820229996184*z6*z10-16966746450788532887667021097207983287763467659215848909517660551563897068933988596325499374274482469358398930518574306354301386616022437704097317238012132931455108182447919069036464904600*z9*z10+23245500560081733823405305183154788889826677162644988799869976435196833167143124438304370823844348970293857114558787750102605233400269469241732432183893434750187884488829733453167402399062250*z10^2-51695157900047245885466198263258490909618709961451106248966030674850736105263947327728596222975325715579978915127919028237331317520435194774805302481290472406207413635586134800661605000*z2+3237950398540290286846197131301379251975091275299196546794892301046609917830336105330274909964523029165726003728246834875545386610535408435318924314498760916727989291263383927926733306*z5+26200104712650185249965007920740064271953437466752684537818921157149652371972101837004743467609441796824509692767199618228530575196963678877203330371191438306583706438993858756746182090*z6-28793325929207822740805773708347745176276463187165962323296038004557697513642596754945877510961237312928190998974592131237878877107645289397573305739360345550108595363913941000620903244*z9+93361433563210819299850805474487394566576404136404865651994310156836336955829141544724829763056492511062101905908726817640372721085148478773962789204469505891768453710240648827533366250270*z10+113819449510729795612436670571525782223336901701129033027728597950684080416357513143274338503776403899354475563602375504277249266022579240352433855619165671564755068944374952112373780259, 32630316872779672910092696670170057877725839270350975634990983256193380288443918614360407901854625126040859263902502400*z4*z5*z6+8379354048688956451975419612655136149370986119597231281688559924773516497082845650070990408086654744659107271232511466328425*z4*z5*z10-4886069264365885261209450826730078154009181023465082209546669948539770270542208664770567193394528997277596358175675128038800*z1*z6*z10-3561107337869553711059905058071186434332966178845068097364184212714893307119264769071819194475835148951976660913466449705000*z3*z6*z10+9135478425356884332802518499153947961296183838330857986557379663746575285345045807651625755348592988762227250862119212689750*z4*z6*z10+91855608905984382705235814090848250141406068498137194990730253835618983375903674599964718847321882735485370612915616130400000*z1*z9*z10-120632400870830669317800428203290950223243658244648460526699557656476183308811476019348364153032544571834959368751157082240800*z3*z9*z10+29294322856735026675972675282202905651104927316413463429823275711379133676569718279545726192399842530753521339573152848180000*z4*z9*z10-6103991153128043698386259160904064120075115755685014150643281324139145021734242459062903889862986647966958561957906836618515625*z1*z10^2+10436603568946936101738722128024513283787957669672057595139815862145849865255838518851091123824365202654721987742796935068593750*z3*z10^2-13722412296464154728389131321135811662606164001586603849691691131140942416782979732380094964993430653335359325933057881924488125*z4*z10^2-10634526493531123994671847130505745728231934611519176861113005826465212923156057788032983504267483942485161798322627070600*z1*z2+55372960818158856488475840098810809969532920408629841153798378781629703572109428553193652423000795561438987369190262427804*z2*z3-38868948115824206870726405870815645814663964820930989848693488861122609689943665100060191587265409293903206085694816023252*z2*z4+15213736799416604696979106289438059040951761925483929520488785010072654801664331357561171710815417216357900965296459673076*z1*z5+11862341602039633671050522465480282526322979897849384056413712934770069761009804351041337289198440532548118420970580920326*z3*z5+9670046324661800315821054263802804519936120885820601291633819962962735768462700208243402950967665519434801576287061044975*z4*z5-11591357729253677956183273648632400727647179088669524764647073697668556598681595313425035173050652661603289843707752109274*z1*z6-43496710638208568354343260657831650609006643406576180113509616778297510919847938838043850871084618737062611350891207367926*z3*z6+56434739649245417639326039655297573285411046835227182394212393228047011126285795537767071964374910810451917820792804308326*z4*z6+416647423228774230110037292956950897165049650416156673599232689359589217110948362145292173054823599933891049267874785299200*z1*z9-548241791365110058258721539375333055075918595666116861194859275590595671411945724950972821745687842225926104811944571860000*z3*z9+133904111794971887648556622523911967566094544879040513380949332567833463695820745852099674634539969607999546641171468448800*z4*z9-28972446524828379021740595298215575039681981119984000036166291111240465983363785314534637541690814321850299454727023138526050*z1*z10+55930362938269705581106300544998673976949302201968685634894052108879123732802191106637436636574828480815043344481248955773700*z3*z10-88392285735941769425414627862912037136827112629607126072385989181562984005066973062128631713531692256060795603910977522061150*z4*z10+14092260572173457420644542224142701785595013553645409160762522569854782855872124100999477972341138014962420516124830915575*z1+133078002964316030812338812420926260260270089688326262395120323349385614241725435856609967262623561541314996251724855859354*z3-237579285312769686292852586266998376366059001388041114856941338644356334388508524281951952979627319239102479171945423140477*z4, 2039394804548729556880793541885628617357864954396935977186936453512086268027744913397525493865914070377553703993906400*z3*z5*z6+867877896168597323025874134443898073755408316942933006912650637171279154659218513250324770822461015176263809608265501340000*z4*z5*z10-406382439734824840211132746407144406442020972914901412849839433030687245492273307723952588604379381120133629094515101525200*z1*z6*z10-342625274244085669936116644304271177897822030039414349184383344635854756122715658891822476969239419205798047330735049360500*z3*z6*z10+911980890694515790721043153907781276817721894491972238614363595483947339474622474488449455825915482008329258591598511708600*z4*z6*z10+7569565297196053873469341130339450971146644357445377814351284649889627042072048343403853569809370961415695343001382295160000*z1*z9*z10-13104872271492392424968455165533372247396166686250601836873361776494565444289777294816337032064391196418239165496695869758200*z3*z9*z10+5605878044736694537839386140013366191050011283304999307200064349931996078362344377926842566371845722101389029525318874115000*z4*z9*z10-326107974751403811427091363348484606737994932370881201799583108731000371086296220454122449348979650470924769283051368952265625*z1*z10^2+416774591297930236865109222184687334010595141906894565551574584669568716239948193580010586051500256668489397200816789361171875*z3*z10^2-1201335270142751060773760720532832145313628087527250705746484775580734991431444802157478590704132205037264847075885930918326250*z4*z10^2-1578057071021438261682686035122208293152856295297697047004813001230341506773237401748816434479423054115002656697330987600*z1*z2+6571250036993351930404538627217786805830691205188375980588798268556965476839293252878916376904643457030420408578697041208*z2*z3-4353094642725159081974729393834626274009546325954694970242122440693962127197104222564296633237652537337417625870147905504*z2*z4+1575337107472311041458497729252775784599610454852092787543132230554087028650521092528853469747771649658061980974073557552*z1*z5+1187790779432731543885048319232459530297688312440617470749176797690863984452020609364943776267532472771403440388197807152*z3*z5+1042635758175278074330862343431155643631385495590554208996862450638320138688633171449359008218229739158069358609477924800*z4*z5-321606854174560628846834455568696370518337597375802235537482525193196445597822213927509280917374577371798709339192982648*z1*z6-4593581692457744269251317501139873982980563609281063751205390034870712502533753656839277186898189322898503388221444309752*z3*z6+5451575282972874377216224023531137429315840412297185205283990224675669171935379894602941494984439331624943875823131074952*z4*z6+34704202123550787760297360474611883929547543947958968396419692695655566790996908790752358082823859353602061742467465662400*z1*z9-59820615152573826337046400800656156205287253274419347332164176660048546325936637886537765835093963011772254763427599825400*z3*z9+25431366846033769800367969052234157735666737016420882941580311063846851004300850081021154182868404113303192704199734198200*z4*z9-800109963331758929193336201267292081761872457074557806755536832645819293112925707233648347238104794616982473867032035582950*z1*z10-400334608994962487596602684560700526739838391062410262152560328142384377582021953165068166361973810027546246385484569126950*z3*z10-6399376454522911498333622568385630529038753638048756994463264661988300219756677432459393231825027037793922479109519943988700*z4*z10+4400066714575318897708004092248168862028495309390924215414866800026489081286400777254185631266958491963765785986961036675*z1-37579539130811168409349712587775603892437419608178570632222162842324983725662652238700294893850036387030211582482730217*z3-16544631579048663337401739271106106673487722145050334104012180631944974246389655249303501985466303078492924470503613376754*z4, 3735225951059978858184324243683472902997192576011682211407861425157952286876823816929953633796571984675682768096706730851741275924024681764489446749635316496287508419916714580938880*z2*z5*z6-14974055875223691465406201480181477412248874335693436754462082786785234770157629762593971810715980281495334135627455312609243924969727476867895800798540670735442119078375015390053069754800*z5*z10^2-25620747069170203250227698735890456155036946116312208753982669413070742731595889673835876044617282571674809854688351480036498439348926158223884287286441800120208171618903683504188625702550*z6*z10^2+394341091062826677952688380427682112005433187288469741804966120999836518148494005102472437350349664648907372139384746186173962791377492621491823893728348358150595845888551994278815295505000*z9*z10^2-87015705137949143042188501469384365296960607202759354422400750954738770392945905690531497703021342284778335916656623216536987037840263040729401829014237624843806643185725697439484012769921875*z10^3-4589323298535701527324660956213994194988000999399500781009552026462483353323871727752706801059096392194894771499692794213998750520894148140543150025374853214821469920833147269914832*z2^2+3799406858772018553311465720124867779425219954050041110831997801309194984585693222822562176346950003559878151468750839069634010613165950035468522462999934429478001813290173039889890*z4^2+21674638920399742665796681262651314698898601825234386726960787645567840463130650139159014305214131289729857903302071001137766962005718906506812854774053825085119928486838848235087512*z2*z5+8263059388389222340101109872919701615306390846629076240816691110974922219290412697350515306673190901751809852803289052972012019367422486962958051450073128550208976655752711269512650*z5^2-27786189560327897841423800310722889730069176087437488008725891762928281200349460362528063693615634068285582463221403805512693835001408064426057042153317118209682420133234321789817856*z2*z6-11873458067264909110997024571492300539580497494540684134241744310050955161024938663355367541282111552805735566841941911041283819765523211759480944489409839480127538465948549051204256*z5*z6-3355593545238431657241411980329650750398166531056282990938180268311996388526314430487977382554280289630639710351763417411775103862964342867890140829728071563583311582884632104810594*z6^2-51997318599140453499549807450525121329560163117379997608355297010630615850301934670484232430094045940288345262584061723934344245519512660847736092186443961904755899302777419629710592*z2*z9-38318729657579409798336819193601993905312156298108563587248632537643342929442807170514900110713697575220373250929870084978428073137176650854675717564160165013035311871387779468583552*z5*z9-79533336913183863418727640605412657679614654580122096957574553208013383724046616107548792500962000575534433148684985676342733991430643879554866351318379512245461461897964518872486528*z6*z9-1323123358748642668175510125606349668077507673341924742327867953832551547631721374893146333768267020157353118826217084860969386449830000396969474164326705645465445572758487040000*z9^2+504427444384977486821475236286389650905147706088770870407055294576572073769314961348486009378711232447634248392643893895997070120197264580139912874193346871442102430426958099233025792832*z2*z10-85710081345999757095018745294509946952875456045938604736590815562091981040212151134025645690169480144908276042411827046685700902796934955623869500775607566700912361994840135823791655996*z5*z10-378089566539122568260504527370471210078210366707046305523095092170885459854678565371260983101727440335169259903843096925956853911227416415988493058285820681134412888142230125489654537184*z6*z10+3230657259222964967407343050170571229583329767882188023377927851555821535309843275955023704397718662479974267541432250083989135647009452866603219299993236232280141104689288423985095035600*z9*z10-1043613487365201078317792217380359781750280154010163916157880615673417874751162904376628667795274264770362742079887372028725353557486032779991286304920995998928478745419814127537757073189000*z10^2+2218313278627495769869203917235503288999762475522334580571469838531778749318546418175253736909953201173620006283040500882675465791708568217317057524120266750533456572319906235382996000*z2-90204031556612445720610298367524320558307502383869533983507256972820017402472088946095162187775203000524950833815444019558508791401599893307627526065028533127381567014031595099554516*z5-1160969177415537964278567333409795325954448808280975854178057494274896916296404036214395751306676871879126525758632844357509407481481660823520819121265141816011425429629560354544651450*z6+6511709035057074358187179042145889483189658890826395970283546857416734920003331270734689330949643323975775189019206532201796265348673413592973015316194719506857496379982491319466336744*z9-3624949691310997563831448924467969498388983760066198501912029181002091622532200294215837000761669005725046831599524181700624678203971072707299343837555034818793964484525688524499320955555*z10-2401031620569208948505509252551559336521033708114621602916034217399129146800961093954132917039323321012287960027608303217133716450394649615789314757135727825973507056478945931564159404, 32630316872779672910092696670170057877725839270350975634990983256193380288443918614360407901854625126040859263902502400*z1*z5*z6+10757539014971835612329083971557099056618379604294098159150313280745380648476171985352539797107070611694218997582707496441075*z4*z5*z10-4371670950869571600552137674257480957130021209560485797865899537373598100301422682635272302872162876297621756982821121470000*z1*z6*z10-3214376522777553697238968787221266580026938923944321710403136011793352835085649989516625527684248597912357000200098707341400*z3*z6*z10+10668834039686986997997994808047670977404651488818576828060329396241695185307860709717940209779036051911486081847038512671250*z4*z6*z10+82417705443092806830964750267507222612038512422693923960984970919836691901224533505629715392249671070495333321046336032800000*z1*z9*z10-128569491072772654580315429914300270610463994425483979486187384762276313565147384619395562997742709066477504922386879763880800*z3*z9*z10+46823806107859299957973396753324636869730120040963653524703601867078046680414239794139907180971859079683223337976754460380000*z4*z9*z10-4158527110414333879970829882049260150243670626130196017206583202733271078345078312676806058439002105597340810829606690864921875*z1*z10^2+3990846625315245831884008014748977715571059211437311035818680036571314402506603943785787370507370058464284987349246253352031250*z3*z10^2-10791331214065832004990423592207533865880163675079044989844691118571671482833009458100772987557548067370738801231117087889679375*z4*z10^2-15847449673532228190458017515573711477922772515540195700237439397449679927726280527061221839382825132350299755737288960600*z1*z2+84254452526139941659525639478250654656956507005095272884687740678431828393693104708190349266479688322487409839539180709748*z2*z3-62528723560491685285723474115420165252949804537269069919805004422848050430303390986355995910800223897278649992189522773724*z2*z4+20423322745365867206052181008158866349440251605924729934863437160493509327570368666479894602013570665396308037307567185212*z1*z5+16844225875134976173429046327298725700379312135471800567865959694711866630355773719609019623097688020440714320558596968162*z3*z5+10016618404926715811850261229223643159484681208322478772249360575401176285594855942860203091804634631879182645375942666325*z4*z5-379818747347262301869333239887012456612989533171211338685312774348069016020753922031390363218377832191325160525865514238*z1*z6-50225106720818413581331089386502396299765879605145464799868952265040778167505823333706638245348216874899386768780263813362*z3*z6+62601224255903938311081248707544550028737893899517463683790613214255516232641151675266068129744878869096310614985428864962*z4*z6+376611976264678867677196714737807268356445616264698245571118759274155273033536407267762410989414582464795878181775665004800*z1*z9-586557317988062977357764939986640551537630724031120627457207959002268305580784266355591838704582120441618112483570984021600*z3*z9+212944528582616469784180554580060877371208379538024984314960085644252625497846297953596721773123301074825412870256535816800*z4*z9-14326895032233603215041306918355409427060135923163651158366691858978223940257360926928662984842429435991028513544267875313750*z1*z10-6135096121115512275427026065032337485503461544422973942458674538732534084196302942547935431353607517624231023726027093115700*z3*z10-52034475103411245722157897847280073538591428538894769648831736807751411252601721285051882570108437249769033605429139404123850*z4*z10+34688087446429473079331418098070091687938953220563636376251689354740199641996671756684175065859361507026860561939251387725*z1+13800382719716837955351827729217132540803153956135522336982124061789102704213790273045352198284052459972562596959809765598*z3-157620499955725561655572099445868766358440700251812470988223425652385934595961431060421082589611065423285181597462715133999*z4, 2868653530414063763085561019148907189501843898376971938361237574521307356321400691402204390755767284230924365898270769294137299909650955595127895103719923069148806466496036798161059840*z4^2*z6-482685726379252695919568081634380158353832120864388437032447750062472011388186596323409185444909776789421345332731086546505992686818257371886743575094924424161126860313839326468432167062265600*z5*z10^2-865702246525027331480512988037134374373538660699781056969862622930744485336732651910109081747538360813135007901837512143975554836942553653787779936448739861417771621376170851550464499506479850*z6*z10^2+9130526657069900258346507209482851014977483326047848194195473693286855922882303464956813285008578866460043441398413097600213359824894389318365760862700341813023960199879014534938015618528235000*z9*z10^2-4371844584738250630285055833548164734840383625935306109756376793988750806708324894760153883559453551095000600408286274618285165736735948287802106690182072971568224207557099566362155302666159921875*z10^3-781247668814890978119621675162579006697125408014741253564927256674224045140554157576305086255542627177491514692012292574380795249038195518139848985603554828618757881457952902630790858384*z2^2-347726882925487901477910441965360316844224654999184948682940687565396326372690893127563522646937893692227016198949950629898670655965945448186369169838854596297739470158336275116018612030*z4^2+201052422328990396312410785691068899543184799952545060152958236357187206848128921506039261553431465053030580697036035990160871047601129036535902493267370343756100072444325215710885626344*z2*z5-324880735995524679192322417448230699697905743294538523817598424920721334226913148327091869251615276693642558649192335813011585624129222105653083233861996086370642141328346905426713473590*z5^2+217768801155082531565820992321895997260801699071156586127917608961013957750747794957820530989690695611705664293483236926013611617097500928475695241714875043375366010387003338985080480768*z2*z6-161485754077704612227759459679980264869739410805297165089081367871250257488286883291108894945109172275757463494307547767457777529023802654392189404700328826122396919398400437154774749792*z5*z6-26018781195371817095880955761778275594492359941954622838810888639471126488663072834305418617895900022221206025685317409269487190442982571421972065734159908276360604388326321328374907458*z6^2-1722774968649108556115352337077618506350576410802096741815479228626947725769531680214494658365595197862380560220350957158883780828587050255116899594389856096366989952367723168497660999424*z2*z9-1689518280674290136409747003462546294175012173070759380020996027956984773500489833640163541358496193241225868727471047303640438391181745202289327744979081562085445281714085514686047874944*z5*z9-3395042842054234597066421859734569876622501579429051275627529445792185044591397902972032740374975887470992479203393902438498599418167591388134824808605586910681745845396743977086718214016*z6*z9-54547754521888418571698609793713919090404132749815350927111489464799035446080154336493665636437553152381078952115753229026357496429978324166728603136093573882941860532415925370880000*z9^2+17213098677198469026260200756844655807636104939916415208205105374252743606963219022447262452199229484998995580694635266559783613392348424725265635278793013699277827082588732803524177621558304*z2*z10-3032697808200187884955401580479133900398159244205463242550814199995941271604433488990953405569862310126691008673428569577230388428316012781361945839202060260061868612234724990230948311592012*z5*z10-12634864557037402305017782821792713714946894381432185830190234924459557293989026472643746511043798965583207687485878748215586512758314587705284246446436399140629336189134299585577596711605048*z6*z10+77234951421756585037708605454890650075986754863409770795295374117593828044316485529581888760573934530726231030762254465297139561625102897479913484810495450602480812990097789413070790481673200*z9*z10-63811606656450326518952667498518861800595229262511634278590365631926122702887502126652657677683913839815399426766975212189822559661234322401261478655614490796972193258631191229914670615510803000*z10^2+75222816961683754154503924051644450676170285719032462371623907366150863280796939588391719891686392812087450984596582425005664676435647902741674312565782475977992787321008074869117020670720*z2-4574752892649191761058646567146561491683950143766807855128141392740625230829282458078632925783401036784155491395987554564374306734124963907973357084575523173091957478383421425819643845332*z5-37319619370008860837649361636958437858114000018796281241658204234373914317236591562044927690471633057725736479257665240123888201732458435891875513369579783526685023311583167409917821770830*z6+160573836186432831478813231512839782063719930279014784688549820199452408375904234301218766750358484485715677049374673700017972724313161267361305402877821798556506295034716233577574038901368*z9-339045757424019336320456288620646309904852039162915715465503689848554224795945019549041258303910122818201582523943301107184009054818986355061417896391507185723765730096126904677202308619527235*z10-711746831889590960390580496682161483475964799382971837477840079296098966806468823635971388246150246790714070034373709964821311459159184428323159858275720434334618439691301732908153778189948, 43507089163706230546790262226893410503634452360467967513321311008257840384591891485813877202472833501387812351870003200*z2*z4*z6+3091874202608063103787320983092713750962683710269180984611791665709088355951082795953435342312045169449440855138858580269575*z4*z5*z10-791863706622755298130552913351512377319090378010095522644372859120910608113587281165745489444182737095541962715353500460400*z1*z6*z10-984618551272589546231208020813613321536786396661814855103240768560468209911364129702012281775284761044995141884877342204400*z3*z6*z10+2992750965935441458284167432947262231644796828352040585848615231614383549036225156597423537008042294025638377683946709483450*z4*z6*z10+15921445840386520341898443040900347670083199622087705289699128649183237803288513995845283391703070553841734076315970725120000*z1*z9*z10-48500798874446435791756452043581326339700579633136030146602389596974941716235203706673198387565210525116898986783671054171200*z3*z9*z10+32915143600026351197554529783938410036169659906453841825259837956046129582177227537158766981280240132625457212882149438760000*z4*z9*z10+576162665905407140902519519290573742958138386641778792442006975115546287377349601031000968753684200712169104944113865748515625*z1*z10^2-2223431666788615689167255136910053510603457597114025851281676792210633572732231010531472547418942593494474211873097005390468750*z3*z10^2-2579148658527878850970355137659578255299346960794309051892298406833435283679004266765936023462368483214364701573044534876931875*z4*z10^2-8071432651198603133134627046774647059518509215666592981829928898082668764590474349139506188348073684867670609224671950200*z1*z2+28725298717620007032722761361890743057764700946072654140417618007220940441367636777778796285152988899376102566383752815204*z2*z3-18394349898292555238174186676525752348167159730396664596476684729452187489735152188343680146218836326624757585335273851052*z2*z4+5736036737290132617764882456702523542545150883242775509856832066012413786215989008275264347277671979292935325755563265676*z1*z5+4303602840082904696150193568118189899455277163035675874090467428237022041776069776913555964584877713059254757217880984026*z3*z5+3585831228347857137667771923915015071416070909429372328346931654359325774345096540002792530328836419533569888800176944225*z4*z5+4416201255996236459197473536737009318729065842858701955884055294539701752320464907874013619485016694795094551968945851626*z1*z6-16369172222864599268275653266473232894754491350943655782166752643747027042176457362338497255413792090452477948811349067226*z3*z6+16641165344550827134512716703280476821059722940932416239520138794200639689007486084604068662772460007891560531298278496426*z4*z6+75489485772847479625615301149709610605555276798155150477132225553989317837550742904598707919812628210889501481193931673600*z1*z9-222746022678920257974506636913260018366740406747547210723143607124530817808412936883547871794507854525053018777182439950400*z3*z9+148755111944866529010173783449953917075644866050251972653502509424225146575923887178389708174416820741859757233097487067200*z4*z9+9283991110674353299691037848267421176062236036347786270668193422529117349625211036345543003124254642105446052356618756592850*z1*z10-33566575360924825317671948643972991440670413595557142832421752950032512868827184597993350218604681778120235807435153667903100*z3*z10-5553252100791409221483544308173857017734128045081150321964425428731739024538247522578855156282392724773625948877095635884250*z4*z10+30321130401672788224388409251376568821949849746290748216141097797536898438381525165397313113325361559982617551073648901625*z1-66610575725505969844444023215123607151283019049253668118311071881238142857584044160662004279266405253896573351950797372746*z3-14172760894359640544386670448300951019115628688741001351953053010753300140877706854131815352319888477983622411147468186027*z4, 717163382603515940771390254787226797375460974594242984590309393630326839080350172850551097688941821057731091474567692323534324977412738898781973775929980767287201616624009199540264960*z1*z4*z6-752893783573663121823920772164454988145044225733820693262024122456470796401303742043311313546017665236046820512913354211745474936793010647181221816539271244676234152736931780810301618378769100*z5*z10^2-1042548113951972012224263166128713217038057868985533415178289067651943786527158364630684413674932059851983171005710205725846099115436101391000212235987346975161680637695594567247931206317899475*z6*z10^2-768625126675734293844583111688764013343104806527298628446782574024171370765001489156551742266023046058712762197262449791061804406833586572442370290930703436374358068431192289533984561731652500*z9*z10^2-3262576161054013692343346316478541689559538944028425467264833977752108516837619386404712962461250155847829624202930536314218747563267396251563825506013954920015940759459693570506790485303712859375*z10^3-550792866018388072843907365670188766303136842911393780862887811774022877000023941835639264900518857073252247682232559729974342040696987804507182581248846894026570695920900723661125315904*z2^2-2868653530414063763085561019148907189501843898376971938361237574521307356321400691402204390755767284230924365898270769294137299909650955595127895103719923069148806466496036798161059840*z1*z4+132158596205547672350587322005080643496171055292483574748672805393152376211044843755817308965677224327622329220075197863588862370525532185891493520637117549455751314046864495791966519650*z4^2+1333051291784091490700538415207084459289314461361580433416368593974381480921613150324513638111979598101461323460349613795164547526550044370013756033489659357115777357464111786158406419564*z2*z5+156635163223387579078492411333812509885513815617334244869359401864877568379965825523050690123752085593577895457149644109949839592410561843059680592965669722939189921482729782177421741450*z5^2-1584473409048313097060135685671617614349225351236559809583692726218221314238544341935029288754834892189732269847421433182509049145996825074871599517059266512847158207936275747553688928512*z2*z6-697435573234718897647446275099120588303192865092137797291833218714281911297132026159677171620675639647574507520846052071035556479688382239774151806112402834202476949190753790086132145872*z5*z6-279886345505001474621197019311269598450445287539607701278933849018139614156407405488364525589903838133712666165198617557024339741609395383828733256817467616278516262380203095132566834338*z6^2-3674245729592629737397424669480758040194151311189494835659757082853938374458404075642854942457271594980324101092912691888210952705652007123600479689157295017980376012626060736326697556864*z2*z9-3358655540123565373126328068971748528056603327229822181291373325372803829529123885512745075807547098494828761114082135129693132521170876880286131467972546505416340834916766816045374762944*z5*z9-6818028224351229471756735252394121651950073401539452536932635490271697405477800696255533275838394082890654034941219197161063230419678675024047358793870598616946149462699075898164706088896*z6*z9-110347047780151350170144748338458095323975037480351092516034005452991001868670173551435286797102052837467004825724692297103314172693710757958449620559825615801428871614294020218880000*z9^2+18622666771387855335549361069737936796939568206175785153319253711180452555564946805516107572941642799004028714696467491346682335550172407406837751168848893172596966312860162507978196817708984*z2*z10-5002481115807153200197216655384008231752310915929287368997502284970607995517836436190766766617036878818413229840889542065805951667244196522547558511298906058901333368712858769060571419958192*z5*z10-14691683187884852776902970892394653335980715791931078458160654889228076711272206142675144705835299838273603617810647314150746489165623964535461713022684277484106731389627750784209229701673958*z6*z10-19105683325229262683398526972895306654642010591487965381088378887107552350907565443687761377900818837277211165541453625414687753461624865624543829504808196690173324428138327446449989374981800*z9*z10-40096891839013315410025529853265225756433454910238852045827445319466665653737754070231537593163786068486287423378494720597214466622713530805537229816343305688472505090026597231991973296971481000*z10^2+81005959154584437911195817966502936019597968180780718925414775011699111880094265637202471828243441379594248229872137624639954812362472958365750176890543516909912178125843096930011058924440*z2-8133638148005751108379649737885024342627884044464028059562759659110032755324147823560995914912066719302060454791607001945966384158352647844885054781349109168461646643245515903161634471132*z5-43378800683870049993063924875222232448324898078846813957656598703403367739114303298410213371685372118807659288152085114370634492621509873951604189497981503977129604559090756934431322800775*z6-74472152061711595032637016688376721850496398711681000609429928699998454058118385468649443757058576033771840678804781505492311152232466966196576562691947780755109341698120270012823085967572*z9-146514885316758855670800515157725433968713633873092632410582632945122042902691672940365627989579636731880123330292007144787673923087095235663191469319514324656723969355502225250909117949133295*z10-121572385146809439558858331635497510652665077863210877318399435839595110772819820428500866194696954955869143491258492066746480275025998581707113499265269694598492689029956785619149595216388, 84974783522863731536699730911901192389911039766538999049455685563003594501156038058230228911079752932398070999746100*z2*z3*z6+523291659823331618265649171708416308084936816557624702945217452515878613066289139724482352659793827216513829670014536175*z4*z5*z10-147199922360675519826169157103076832085720150991924334648381416531618298464825278402011945610080168900951386096252005600*z1*z6*z10-195276937621435523923074867735426867823139211034281150713472775058032474081904105122051404723911326142769071938285743600*z3*z6*z10+526450734383887809369239852278984801065416353792880334411816361861092715882298551517507505694416285647684540197416152550*z4*z6*z10+5870137354172733727300984160064947551908210572588540924972003041024915161933218380914851798637163635568057648509070980000*z1*z9*z10-10217808204816837808230921968272887619596817209478147937630256644611995367349998257617324720697624812928516442676342131800*z3*z9*z10+4401665931034359288277168595094688382682471440483429725637725653093747203649524677517441745133871399977379949620310615000*z4*z9*z10-117536178502711048047857577359235350136371002997467579727461342798112786804374239840673243126188219386946446034276437109375*z1*z10^2+361763609257594197903196733910079717285194916818356629298184149521194981940189837889600392024376613982831176975821643984375*z3*z10^2-355938803997981221204426739900705266666167589327552464089085472078747508625707009360805156739212851968143754608526465930625*z4*z10^2-1259307651919584838762447913434000684774906790875173546848563962746715889027048268314570371362053185346795988462803800*z1*z2+4751444878055981729167585293757167802412811906002120612235919870778144923653362829458915244006453580676866261084244816*z2*z3-2944961550659804634191285753766454497086701799125250203784283871070396581828247646356283241472455208675396944502020708*z2*z4+1050709310205308588471242406801729288374487067021030040643082406201845043007310825199349553446813317243687738288889654*z1*z5+882414521097618368250872866461331672005869702119960712846063692999260763530952954614776501137908895050858334520439479*z3*z5+479234732979778922531485287477150895869044773241518033570448539665800569588932793466933943770909107528881290911597725*z4*z5+624494059735200777082189011160330162033299952680880326739362168051654408416414022320693920722693569401445218312528454*z1*z6-2911091939673075075752504531478708548930843645143143621279966593491463158127828246419045867543394468210321240440313054*z3*z6+2861135136005361629349178209049044387920169806201686054332550282052165577350338913550883064516729111933595923210790854*z4*z6+26921596403364641286610940284218144493594282520193829006680157487618197053346553642009595550927028471245749885084218400*z1*z9-46599495842297191621002830615935587019781615276631692324732553121219927690986887938044953942054660564690122908692172600*z3*z9+19918859271136527030549646076348935853630307048468895922124753860826296274637930070676703666470100894182973725168415800*z4*z9-89082757056711378719968104776836561986154039667452895617602746459361046780977091724091696822085213946048150665632260100*z1*z10+4192653139328359958948058724991392803008028977996229893248422795101494086845929163720834182614269638011009994597121687100*z3*z10-3820505192447568726832871966805739899443222113025456675178471547730829296112184500294878560914606324856003082261820738750*z4*z10+2147328163136599667169748988181405593421599809044695227290336091697081201930287058198051675202886248578057737424152875*z1+17883359807870006025174338147193480937021789852813653974780871572529881700777330895372657822713495595786927569661336841*z3-16615659594190892680718682143404054879427586939098635591345931531339511791773504337741589388972511954095552584469130833*z4, 2801419463294984143638243182762604677247894432008761658555896068868464215157617862697465225347428988506762076072530048138805956943018511323367085062226487372215631314937535935704160*z1*z3*z6-513463620569729081600977298802848527306463092101936123286627618663453846991884700091615985310598454561018921351483790077549189136008782627627442437715864240400193054708078573262212117657450*z5*z10^2-1021798381130668558743560015935562325395291201114939819206317007681751068365919003551541825332848147048059722102787159811654208078908039373696323372219238936383652741530650345254355988368200*z6*z10^2-4754272778739295614218378963616585695606278105594033472055789935051547244500622799883241995722004798921486191038673575490330198526563323663046291854965961285722171831095261887893322666192500*z9*z10^2-2560652295745899355780597608050198526664823437151889662696815774166394265828551765266710716875216266347259315098716587126078349802762797724926285437863527114331413719811207574412861099193765625*z10^3-375698365716645597618821408991956501742384719548298649796209985121306461311305956285144365616154620668360426623474725070508693549515203853307808255872478639958921134218196820519997008*z2^2-11205677853179936574552972731050418708991577728035046634223584275473856860630471450789860901389715954027048304290120192555223827772074045293468340248905949488862525259750143742816640*z1*z3+510035105070834891508708479218387181871769921118031090500458845038303840022202263796597791902201042858747722282684081620594097796370869693204085476240206259440803245496875858848524675*z4^2+1286602704739756795656817354701647744596309967018816298063235784789193282934772324735058642621172186600398800460237557426110767317809438280889740565702605304336495276572790421883837248*z2*z5+540835735365289287615319461715894533043144605635848204411915617224291323888377591861102114791950662096811990457049609067216539330295886276050923893135731747272121689049262094526337255*z5^2-1702855135706274468644829022134093058100569067475163092866857723046658796824599982946259959990119525724090049528751198800064332871151670119632048748465573124380787337230291743100409344*z2*z6-692992037854311632351126220121721720242752952913706480008893756306636441072074367714740560123960374558677756236146210304595892615700624159265341430840711282550143194174117025822180864*z5*z6-661786484935544158258780833317014516453267684247459335507962059998430285995824058565926205197252206605698056860750403737882902134232408653202209371738159025759841487630894818109144451*z6^2-4138448460723800680801026728253498620115898448363128735837874791112199294792698828086330785708841304775969041978618344244392873145054043601469936852988403764273532114446117658963365248*z2*z9-3718293273684585937090400545532306666967002394854924380227487901602917445798473588260704702233702719522619010661212592249257276134109806321396616603044318426739736949337344285599318208*z5*z9-7575279564136703901166917315452550129862015343965551347619479737160072450378579695541468746045508816720894580686299580981530670831929407314194689905241395754549878543788875367862343872*z6*z9-122735364373526799419343261162647219318384020325439474758645514485151098015407397742325029198835676309953691933490288248695832072397393319366217165465819891090189930223950684160000*z9^2+22222335205939989765878148293753010428467803998222740621752215204723235858122818769569739123653291456730422738579815112123801965695853792784096786453763420467818406268779984075809893595688*z2*z10-2817152657608610786404781984401269851194386366794062690284972485119770452924043542699877984670748933285135460957218336686255754842511039136788703784974678995197216996446985472668016003344*z5*z10-15854508369811432464237135137599028419471543944416847655157749974919942902694243471017956621687675119286365800905943061267522644490331169153528700486857853783204093072555449880755177650056*z6*z10-57059935961197824646872039344370608278229028284401870852111100568307505980502407856408110748026086713824096259611058630938227432579811234780989625238831998581885456872153982090943536042600*z9*z10-22039310628452797190309828454934055311588291782744700678249903174361095136857546046542425399052095056187556763365390322762233224780250107541614656531546425661380090162114639976841719995605750*z10^2+97399409821487309112697574480884146041307111224420311678854393644484679521254471421087077142870577995341475627426360772313743493746734528666256019128855533655521100837329706830980662440*z2-3185427405692631812095991473135042857287933563021593390938383038775665641228495810964842221563946727833384172617192020438559634927291161004115354900402776587738076780844451252475204534*z5-48607084724521923143056848341618118201855219102752416381735394970660250923668188173239993150387911645576421268225997143000932117690189646765355001512154717035433891624157867412442847520*z6-164963690877382603807754899977070091486522097634527032590529425270142874349303300995686702291101185389769054824878966403290621741069837937183834539393943180953218374755936813274768628404*z9+10861942725422564805444366649465031534951103044615662655890730216242914670522681160333218311212766502783743148229767557215005240741413761067609433406429556871427493003493256800770970619285*z10+366000137214340719225479053218765187372704294233481466830299956862291150010184771036690252812710131644799962272643447260437788193729104924684863232321882090991884843109071120517883601829, 4980301268079971810912432324911297203996256768015576281877148566877269715835765089239938178395429312900910357462275641135655034565366242352652595666180421995050011226555619441251840*z2^2*z6+6708134779896440816838954845054950604787705366387599645771448069745536619844746557649358821258104664462482256250058635520391759301572621867664008091966983675957833885942438638380460710800*z5*z10^2+7874096227534653838086930364595634781342783251982764964459516379910985467035324763862974469113719280700728714072635470113434910509129405779800537874965666242800296582120533251005056105550*z6*z10^2-2980930010030363324922611809541374676022494858661272863003014610297732547696276386318228595774771318456218071528384108115878683297461717928614298994284019236333867951555245010065296405000*z9*z10^2+27001866690124766682243530834915408214304388439460513748616633432919556322336208579788796365963763798653555267776858886339985220423689348661768991514931115895707595589101582914376236318234375*z10^3+3264201550510505784664764248352579650746844002848471978676991764277867286483111739025205477929239069750203450286828172164827339242853943541736095466284127736068940098447887747349392*z2^2-507541329347102071876544723866888921556031434393324671162040072811811611059808026174632525868597368483560445531357269454242416102258569134274099782474931032871805644013250103367770*z4^2-3375082689148775344119434401971660160341359169890663595259274169501675251379742384455495661116115725047970118187840878093303502580628733469036421552496140495150440416676711127555192*z2*z5-712928167229388161365983215519122359206107555706434355853739259841100341400321708642923970395030728873194807167079200564154183978527316565888752207472642765011073236569612341037890*z5^2+13922808356178532609812841662376374500825328040443066638992901534035542799287305353830506203627484545808518133223317259173888086691263338058663286601542951542213672952655349400231936*z2*z6+4542229135621238520263090136078915552636004359731097405509329842140291389220528297960469421252514967803870336065667265870638034997574195976639991046648783353411105532490820695806496*z5*z6-616185352219738385227130912967629308421523767701433160622077496530798607379883160885209549322749873636722789547959380258501369689809403693970088497337871483242966583345029848768806*z6^2+29971330071469842692844977608283914222158480900434860914548617206905055147392734466987610165586536218328442100654544893871155231848944642603123968532640803797124819450094178589516032*z2*z9+26882793880548523700300695018901999194748242367128270827839021792892683230578328080654307962396005439142839617686911746461908480620747107556860795099269646497486465444636622742600832*z5*z9+54640284894646996457665011075515388297375188700087304173943716280581261724082607702324195306387067287785441643616475280190000580125152744242693477636797431703867327438705041362365568*z6*z9+886731491063581133163628098861248499830360748301409354128331452586251670738510787816038691550815809352713394492523837036930682031822716083653527251208721282227885708707184640000*z9^2-135482911639239308077410087557249980847752109715298540487911100802256376542641896413842610068420449956542888416167832659897070139900415598262090105966580464629757017562633874948751357632*z2*z10+45434182939705389799366002215767148063948901818634489906956313753026321472204460219571367115646241006801997013320063873735924969855043569657416382056576973583032682387085085606063183756*z5*z10+108493963309279467373364106488130089948020518845913783029649628406639430292936751909329825452252395123411228514462386180827971916704305649129394871372438168485498528487520882293466726784*z6*z10+79769220138999834972960827821541700422555708127259899578194637280874476324010817788533271704627889407482320614207377332984409386476976711251198011552754826791753648456431931208178300400*z9*z10+349436287348432251266870118895512533215753593390696027294191916156136819506439450200977245109693827836142434177414672635934882552863159639419767913179816263162067980219512963779051340371000*z10^2-585948696364378182180946646493645253646437720623552400237813045893292120383658456208327051230987787626789412904056095159090244441485265835119541806005792076850530451131618881380894240*z2+73289785848744996722281877462589506980835028370978738935892777718047865105956168320948843293871127760714715005059617786119082073518516417537798691899885710419631945541879109967674916*z5+321084667983126415560206605444170598871990286384390732718703096661734816566353067593007103914388357735407297417570591342628627520265019884264981740368938662672839573205073434749302690*z6+451541000574034209363542009134215629767573205947718290556701539766548527887496818315393167825918913445736668103372449738829430428651507110842767512612317327976473816298553281573697656*z9+1430429465859054529331369964834110466467249834872993114033618910325259328595715997790623188422164171446830219465418008812336694614121985139502878094075978690529350535884739018378133888695*z10+1753240645797805741995194652139743635520189265035129674319344123663248915191274951216006402284333013491571311525793538350076519059452272792303080496498172876733714685539926935211687884, 4350708916370623054679026222689341050363445236046796751332131100825784038459189148581387720247283350138781235187000320*z1*z2*z6+199203522082206849325681993607674930795041318081785484986046725647699230249507490497161425929868913090593349062565727471165*z4*z5*z10-110654576823477813114051124622914597028738894103482217106497360812272711152642534185342350598843803653024742179139104417360*z1*z6*z10-121901530385545154264715384024418089935815157148443545708769903220052103773129033040339288202463231957702870994704588362780*z3*z6*z10+234287598882474842021540736739957559784559675379929109021294045397517963215659781878641256131218438734984338414208357988630*z4*z6*z10+2161681615488997680185493567749788528191130373270510616758480845242368145869649643410234269684199827033524017977672461488000*z1*z9*z10-4651388413656537498094072916567352917641875070655690648892535797185564505954793949359633011257537427858503161704070329607920*z3*z9*z10+2517906957225453489043253398131249173990644459933635673811175259169709872597090578903679434530177437833416894662728037238000*z4*z9*z10-48593859798206702853619518437780389740143209447170761055955934062006505435530615025889068171878954152839587729078919767078125*z1*z10^2+112646860609693327152538120366423349835560757267974305538231718523261705206707089069961522693510105719160149412584087635281250*z3*z10^2-412580361161389842100712414678078304746696214020000535718287371312286059247484422062376477746330626895511410294775017457305625*z4*z10^2-577124348273029570294494621789813960916352902587685997583153870116178782778035923865122566791169086866533257800986495720*z1*z2+1477187018458401481086987563514337190885035313038122667175783775987646534296326107777655040304753552161926310738387394412*z2*z3-685799996362164370494222319961041930432492682720107635706733236709677969848701769669485979400919007600422314887902961796*z2*z4+325027199969988538712167451323234328743862951584649839219184339693898398101128936845634843793033615755183393680656374308*z1*z5+194783542200239214261425216013444970809503008637299116960631123363602809187732873963379381897739197776054034305838587038*z3*z5+355229721593157609145476358940446371602772759204849450770030038514932037660496627310965302423905411343255555613730123995*z4*z5-129900882644549782739550417646176155369103887870402372767318855196380180139891684706407810981386602675592424591237639002*z1*z6-1355450347513650400926502132222850901173699412259612343442590696648939808241438591049497187858594776094286953452941633878*z3*z6+1425144041533211800852207711415216848058893834066317944365085764553234587224440692491958349696494144302017412808219074278*z4*z6+10018634232415291340667870999900623989069393929008107632330433468484313110451806094846930858658774938728031399465101623680*z1*z9-21288107692494262713220292985269414933362402584546756129219012015871256175741385468569954561846780280347421915108973174640*z3*z9+11395326346963537425658056323194759836748520229161922954967034996310787107423392765320616399707738263395601911875356939120*z4*z9+145777987833469582102291015917972262325628251879595683698230637747792138744928883668828438278380333554231217803903881916190*z1*z10-146977082302511925255852801024682414431339451678708441921220076469942674043191471686867059077349468755397025010051246840000*z3*z10-2438931094489008325041970571612091448453623830147737180548148063340445663239365407487443608777454286891363602404367284280330*z4*z10+1972236232762699074192318172954583444442280698438819413594337445932377435731963659321540512304997489932638387466399991035*z1-372164600757756053295363566773358583476348991199659907264286179120147724178429652898273136810523350129125135084511348718*z3-5676724311414978312821090964570682284171711557742254778500262236280511367498710482432093006008719969154825576568887420341*z4, 11205677853179936574552972731050418708991577728035046634223584275473856860630471450789860901389715954027048304290120192555223827772074045293468340248905949488862525259750143742816640*z5^3-1061954832102754661497228483990614448815160110405871191448956750417452808602618029757833132460202297638617205934067953505137701612486388279167584174556991821342552273040183894875836030295400*z5*z10^2-1406572125229144302449528070401504984521865906779966061369356403740590513257065616799039558926623883228528402079099880065600626630116491200751315608001797160078508163974181486396114313262650*z6*z10^2+3301381675165734996252766428336809436827924997260077764465321219732542357061696981748268647856823847680564715138021797254034230053078893790208587987614512091487242488125155496580458114965000*z9*z10^2-2834477536722933089323572349327218705789374242684716389186203504894627147931020407477255529310300097219587142708605702987941993191274104501630129838950900215186648363667035021582760099562171875*z10^3+938566838359841398248681048671951226690232735179880375005649101692350911457972220501614903254997884634297093687892349609886710147752321529839475255222424797259922599720850770827599344*z2^2+603961858438703139090702639539859039215966078059453081546389868692899064681535218983809004343700784328015497225345532575373435839110741587512070489820095794620711154526013883433142530*z4^2+1495024267608761648937332439851083728690752154436349295840497188708364011607849185533120811471446288229692374247084618682976260662276012651194594779201919442281477769445244793403974056*z2*z5+652083033339883553195012802231420202924268191478446654633032887029172416962138774834123922020733661473546690320154464637285731024728645339495773141928903207780126529396087322446238730*z5^2-2000908226863638100420208464903468332926748076482958784658747544900945704082173521014935577828809610642557902441330121434695702869059462067421708633153794933917124936743979510187168768*z2*z6-833087886458809139610409664352798882946010893821464807145264870042074621647689672832828903920587818519919420079814288530899884453843873483088948347197630802386186768611532921598223328*z5*z6-803948203721589972334533497889192878812611675795974082942878009462693083108527466467833350642107641091589303713678310163242674987141923866229937710938621976561584475102491341123239042*z6^2-4050086881072616533546803001388855543434003973453869549578301412474201553472205887871907315503261049418534566476518553972213420343428501089767629184456785618713573419609864128513116416*z2*z9-4236653665157602160535096704520409908761973350890956430599022148247014704814467327835291688572632464863634179736615920939910398189753231682362586957174924942939526949750147890856398976*z5*z9-8463892571291100456644034693289150932493462305545785455300144740217142068813143045306806170763939553066343917799834638018809329648700299110101323934465848006597445658215303480336203904*z6*z9-135073874718530175969003013149432946917153373386595194111006771026265811895316187506606318327862661573390782424341551903622952870271260851046906990832863059417982849827461611520000*z9^2+34263547906851556619306584303127328099875565998359587586979752763281233215307659195083007409703609055364313389959552735492365023719950542041380191077311461715795933413829682489442081201856*z2*z10-6849139501307576487661151444215777399112820727908817850792620380083046247226388541334017822125766781629557675888877629819900742501896489260287806607240099242272992392846741963592377032588*z5*z10-22653086106956596039176128618244339313316469376369054105598393609653738745400567188234282818401058679083866960171482092177667863955494461175647790894173299646711599041675536539726398970872*z6*z10+22803063625191349721319088125647955034172475380681891958813643869054589777189174739481549406665361651269869471632877441870443536536596808472855524859036388600006417999437626609488350262800*z9*z10-26797320567719970135407195672390986868558070546773170392895380824865502723590559697869293601924596282786056374391765280544190051250497817192869180264678313697496605790809221723537778932486000*z10^2+158418246324358244720048563142703822556454892853328824862436039061319154218986096353430549625856125028611313811502607371111719753424831316286469810927217749089022062642424473390278464160*z2-9831913893702844398186491097105498267632879975638063050122541354465107515477611044666211356194910500049729014903770856890581932735108354148376888361610202651616240461716800829682415788*z5-74552204491035200564433560603197636842713427310672304198504771857142039338922695398058120532471067382293003047531540393287632422594048131111206151613937714909751586635072817075065803710*z6+30359109254060602559120034388361677085427982343131366915971879647203927022018896636053877936351138470410684237696475881852880576831078632663554600031439122698665468305125140911561577352*z9-1422774568306499378564647128808224436232350660782495206146999415112940437418470398861316847992198309713162064924028638102142598475879246362640787628691315368651530698445101282644849393795*z10+405166304365807388753889768377642756185265441395375617098105821161734310045934717200255799625932020658291607789791991082515687317150206870310413415205023993753584246245759616225807362028, 169949567045727463073399461823802384779822079533077998098911371126007189002312076116460457822159505864796141999492200*z4*z5^2+1550323246162510038506935579306468559321937557643416516258426988852815875972771358535405334682174196394648237174383599700*z4*z5*z10-775127564242303216205116366539398535083053151391633084811904537874665103322385458446529258916502736676042473948880678400*z1*z6*z10-875308872844687651057068429778495764381540732828666402081856524257477535620430055651847339118534703522101087701615406000*z3*z6*z10+1667477046094523362160196562020534069454507535037685081518989198513065399262727733433984434915203468235924325170481712600*z4*z6*z10+12212408117354405709515348343586522547520021163963694773552824012392867590142086609746490472508309669352961059861697760000*z1*z9*z10-35066401091212784617004799286297526864529847517723142671683161473906321144740345659199090472617740400190113810718277446400*z3*z9*z10+23093408876414991631420342351680002054555000427005665184249844121509307977951765400500569408631063036635945017948512960000*z4*z9*z10-669047418650069473609699116257779434521745755245162236631453386201365056521204551242692418324290103591429346827633535625000*z1*z10^2+223088135980549665152468423865705737615622026379807571754560189034528944254579467498914897021354600508210034996126182109375*z3*z10^2-1400170150206899070545450920906986201515310842889858682050916784614823359091893530080004629650308764331926880962677321710000*z4*z10^2-4195769554045275769422169631608280735541779084447878449355536733370651328305684310580144316302926715783172218817436000*z1*z2+9830187986397245327500070846802899490913257484935438741909402972753478316563609168828708627635175377291838563944016784*z2*z3-3775670952380073024233892612903569371032544844858763598933063746270093675674148887727752059671584984179184923563410192*z2*z4+2435123757388128512431626462054154494074050901815964368085360480541134272614463070488617018946266825000897798745783696*z1*z5+1265892566769555737603922460621025778097175226726262282141018861871759423620713842203081401289474944877783251290299696*z3*z5+3038914022568192138644161343175240884110702271515314060529067636574296476282542275385649851318893768583668373067197900*z4*z5-1003785806013427909121449556688932610408093455104893647686459309938229911912632334653682067203469952425777924973380904*z1*z6-9769840530423317172703384077710967190357987824424348232354885855514265428741929822232150048522938695286901193893162496*z3*z6+10296925151175500433944530140442770365560833628286426273596989631448455081505097086395036167203005350493539863495611096*z4*z6+57644766649598449563994089260571220614920441462543120660844428208577653265524389756143517301576784448723905007543443200*z1*z9-161013696281979140065394993802660593597998785504875027715959438981650264264641537754285280818418018367219060441219014400*z3*z9+104437422318317486201928743119479374189396755290195707224503859480274363236732779755326203181863546614252944643769638400*z4*z9-2083302401474532099309928517992954285085526118309401063018249336183363642515062653039771028240353953107308676430974826400*z1*z10-2930983026385188595850050835553172511997104064071296346005777953998833668836074251988179653328026105597620604806256617650*z3*z10+2181591965861019967577166339934721956807028633234082474553155253674901956085836225556135397100703533151892606701361416200*z4*z10+7326722073063855938611129989613445071956137580517135157542437183547708332857462539867536046226178226391486070283134600*z1+38997288680100817986758569231245547610409812148223956027029806533610610690564217126652151272483545477408943874608527559*z3-23562914879443011648688795870299494036216265464569714193044271162992756113221636164371675700741826765005544953334740592*z4, 339899134091454926146798923647604769559644159066155996197822742252014378004624152232920915644319011729592283998984400*z3*z5^2+5351868839060995686563159952261845909028796638328165902097726206302068046651341467329208307173684000457244065061035220100*z4*z5*z10-2106828954177006598247297131631989946373045326935125585614975885089975496023398142727464504117967847828174896568614361600*z1*z6*z10-2666416400271735484824258140604632163660716128356798500969452099246202306027616649397132171697295300199951659455753402000*z3*z6*z10+5754419201438634035617202655407371005849156958161611555317234355202086321827685659213776778996015477965553707834209379000*z4*z6*z10+60032281384831289723392568422786115640543853712917813235304408018174869927439791401165425609225369801761102813417340000000*z1*z9*z10-122903304074988065155926169075938203704711836487069879697583883396630308275824338115962120283037680602881762465140501893600*z3*z9*z10+63695304309465423684365793165712873947858807711017959138790788681756470849903927093833956217534216832653428477000016460000*z4*z9*z10-2301462439657068889191914034747028870972088968663420505515516421397658606938793618846409386662773526838521702056301900000000*z1*z10^2+6052889987130556091562653551311918842224300518389449380357179244380077580789378315072074698689179177911814833155541302109375*z3*z10^2-4415074343301817821419047277400195468141941121371112142650378509154837567995040925360755136690281611288308740550176012045000*z4*z10^2-14104422552929103359607284072931558323216873490732642658641266899356682006970290950402472946868066479135679326693983200*z1*z2+42502895251052381926986206695978990246895132799031806963187451270264327275784238937521701809688396485478542867866601648*z2*z3-25306664366952279064692246612996466371950786800382296479868054412067365700360146306304990494213205270879706506641459024*z2*z4+9526531150483940881675331264218831595078386097112799622066199992475517092005884180490069717063595763650926635321564912*z1*z5+8392336111097414407670414974194352438248873857316356050722931220277819483194865107482564780420277043183266764027722712*z3*z5+6403706345889943091590059735558486312685312344685356666991892437930406190219351193742616512933187672007044430867551900*z4*z5+1522041935498378996179864382616765531198821136648535493058012585293098109280571712689823080492245047318242838998902712*z1*z6-32539516873152745533752451431679725076582520141581218619831585065281086519692766123231916364550848997937458947822689912*z3*z6+33762596920071119201101895125548775317902033935074022262758355448739118318021213688263093000775340827732402576971881912*z4*z6+279028908936672880411436203645281303561169758756266876353683956293197382577180446108767333583884492331519201643920454400*z1*z9-563854676051075983719678675420585370628542890487058940138629325025177904493570577406479716473720544247024533926814444000*z3*z9+288504219252991204832439597907996134052956325215159026302770950643207086439355838089451094410897516722246172259520869600*z4*z9-8278110504802852569893567367021497951170174223321427712693716926483356262675141522929830764398418790197424395054086803600*z1*z10+74492195040995119866070173372305398985684035696678432286307854389682874287065158837231379830682306146032038030357150827150*z3*z10-39817251656619641565308753056711341988309441052793872829715798955747792423640485545615634340620109086440578794929856224800*z4*z10+14620432852842031356502977915749832366627988737824576596635373920862898613936416654567619082703963526382075363133660400*z1+352554277960848032443439249438097744474527576469147468058944421496277089640948383940502004469992247172468064161695212623*z3-238671948741024902106587130347792701574843540405583831799098563645265998999299815555065262839904034323713047095785769224*z4, 14940903804239915432737296974733891611988770304046728845631445700631809147507295267719814535186287938702731072386826923406965103696098727057957786998541265985150033679666858323755520*z2*z5^2+808590015604152771153110087503464766650070041726745608397731062209443292676900624496183846420672484090829195353502860042327096432295770049833984230730491326677173217245936984844430364124200*z5*z10^2+1357012550336971801751999684368612124265753900332767885211119068057050227860771490986027145910725500794316504518977366953972840626092470629089145545717006040507116482949997887127089560208950*z6*z10^2-4975671716100628170059174889378102221879940143058226514237215661069248796208694344788288814192204901243773693666565853497952839931308916911342890048324243900254163853865039073409852605645000*z9*z10^2+4581722030561426804403880625707964104485258336265843036839535169577735093396238716726068789269548343803697776148891388378416082271161617174168715468699925518182302096727428240115233107611171875*z10^3+240818418826284299484001735957109285209713945690326745315261215774776458357120684954030758352615732154689821040065292750459442599364003538531595329631656721214244964373421157234292528*z2^2-55168741153907845982071439396892809030407048509422703919531178759520110388323924607474194349456627675536110254610032764566769793628443316610539739904945560103882220658274234132445810*z4^2-917375068647711439999261492358896561817808862340922408713785165726766220303591755531223659253614433011657305972956404992393283790642264184791609929457640148398222342866670915686160248*z2*z5-86344426341645329801114190543860730112685867201251191614383262914928455665207459928326495059098161268081161983729488887543343284347212258956613366870785465439126608047665505207964730*z5^2+1252655568012458531880573903317239308998432462726099574364448773825357070485401536755518148468003873231635884417790819868163294672330904339879403299680486278651454018362157183272449024*z2*z6+552022620495122969736662614862644898976946181016389556056411551499402405985747521799343939279502476121941733783733986969090510212531885559709080220897264796316336493877906400718483744*z5*z6+240222700077923131584530683294856717953005628379040684356358631202615943855359952837326089346311628238877484204539305840765817964984125775597040990708441778752264350695690484151735026*z6^2+3547574295245299143907797439115578132932175386528905814925787545125246023127756457254035343057260754067443358310612781431962450370127519310802283888735862188844883231754920159816077568*z2*z9+3562578601437230490298429060529327760565805707574070333230218079030840164545798241590453133064682356150954215713194462419435874905520937954862768245610996056549951863117707583918945408*z5*z9+7149312108427941106535416500014385855176523070768736586762850465364008020004238847287019517856979498042617752139251942295198248992048741307591280308344456964002751655768720529288438912*z6*z9+114581004012431143189758515762139350771081757334483317211132924263182111536218724274909684902767405757229465369320673501482625366351459097769087513397930861778558733604509532160000*z9^2-28925524573549177304198968342736243393686787498897844430201708898570678967381907753061017939718867799299062265365734431630502189818443974141566638047382635957135748735309319803641995066528*z2*z10+5215142735965497655473832763731251746369542051392629267341414483967596728340648592167205911825775741192350295935096792088992982073880408244867801903756645363756662494646655415206387526084*z5*z10+20894327512413150412532817806028605080841984616059755984014321758593675736772040593296754778896891378569007415294166579100524261063305675291708833758821460180665470137864716707528985456136*z6*z10-36652494003850621516703438811455611223825998364714830035800955417507921142129849515648656018348745463751361886114351428008143301693916538836670784671416724246271749967816723663452113152400*z9*z10+58037822364547038742241346997933751672934504435487612584206111019431003963717439478823424907066882871868230478061441216421889626842258672528866090816247762266700580006305553625863066467262250*z10^2-127827175281521367663090884260470631881411180329068572106626545639934514169536388185199195268826807399373758206650788099220589765787301972850713084518998795874014503912912042961818376000*z2+7884173444500847252821630636643595986451069135237649085862055799290717235046780160237637831710673259849609064233020409986686927520280838321672787425903247484228275225895658648919190164*z5+65223941011388026243678400684222143318112116955669425008536158346736339104713212246007786893650710752997094151175987578827312782089543386992057978779238694946135814319200895334827104050*z6-59709683796113123023417137628528627602521722711784774329530260424631268557953120503141825789347038954733263063344205932977321671823370038492395141445571886772930758672303803186591842376*z9+232303886048602674276714400999443970660639254396529465075057266170706178086090785210956195045979850226723179256307178386053219217552847927864892802306246049759584592703110871702041902347095*z10+280751317782263605222259929725270810564456882399332562257258006297057184436335240012688301506420426097915481768626367425090435206662700460381749619292400884641367201155362856483516056766, 339899134091454926146798923647604769559644159066155996197822742252014378004624152232920915644319011729592283998984400*z1*z5^2-7181473186616363878017239777962262181141495511959026030058463334215363303209301983703921686511884156084870114131475017700*z4*z5*z10+1666095981267579170156306116246755196129094705500611493951701439442961615932006779710244420313561833453093475839448160000*z1*z6*z10+2194137658766203598479982639528103084885949523588397799395649174892941594609309610285953024617509575317235305547718348400*z3*z6*z10-7327567770042412860971677720062020196154573398398794283901239716812899693358962045274936520254961359255769635274231215000*z4*z6*z10-52105953698732498654327885548185314331005504268763280401463611459598198139276923827403132983008986993745576674874484800000*z1*z9*z10+104975041974198331048070460216341330328904551619740360274891013204166212357890464467085273663138122543722748381145818404800*z3*z9*z10-53539545495745023101980143075961910837877684162999525109672145238350620685357891058149070937509474824997998834205680280000*z4*z9*z10+1855165730216593417526788810588155913235227849670723063526641983452689846193599370644363996810109921128914597106710863750000*z1*z10^2-5861483825753353431773798411926702836264104105091750634477439828438606065571007491819267712465187057588270024435414164609375*z3*z10^2+3724510047311454459312947364611708732675440734688772649073423987620756564570963177782966461164005784271682210900285043045000*z4*z10^2+18492175842684366163406673959451392915194586701663352942723346380435476944980567302319240592748910840721130542990093600*z1*z2-69971882404740886358629112139398186530936315750325951373304392875800173005481019106077503572556314464052296361730671888*z2*z3+49228825145764676206970225068307597239963968934840325546088199855108026047516624417667436822835495102295458656655166544*z2*z4-13987007240984477847821473213557812356189285266252644433025861512941846158849005642298119612338581119543659386764825872*z1*z5-13655262372624745218778596250589394175449504161314922763929446264309996776161227783824970959926433530416093419635894072*z3*z5-4852922161991170128921080777536113719501258808929606893883957714948998621913952047128672640333454126172432455034952700*z4*z5-12729468330441032952214322651364895362172577267571808177052122704824485748521978601103677099167890502664500028290571672*z1*z6+36295237054185052724155665187694798359968527487921111426976838284797649634876585573776862678689121757687627029848047272*z3*z6-37513950687661601242323388842432472958653380402222162289232519561186149503378032647979224147239093856084463212575486872*z4*z6-241607819607608155545968563956027373136330072982848303247587235234551368728478502967748307527875870920790148574419468800*z1*z9+480878020828461454284671704934704689839439112550613655460413265651733854048823166210388745766749401008660172411554929600*z3*z9-242262139836328342316112685555046543768589381751277484348165119446879121477711391468314980111858588152411667797026020800*z4*z9+6569356015128621420384072115701671854108913602717387341560758378916064785399159547674006478953112500224435084299981960000*z1*z10-75561623035203459631649133862678187607116912951545965054352087685207863802814834980461943814788965555831267117831262579550*z3*z10+68445872799741631712600401897794818516256610827282309329395617867621406506423261093955074851248431125962136507529625605600*z4*z10-4610579450606218336274105172950623182381961402113551752396328330061205752064830525562368651052585167346017491371527600*z1-230955084811265040572456115787584753575868613943702271590655013856016247576010037981311213523595587188435252470924968863*z3+239894155476369171403990255983671004709109964429904563719209521624047008451598378186128318204401022627139725509635971944*z4, 717163382603515940771390254787226797375460974594242984590309393630326839080350172850551097688941821057731091474567692323534324977412738898781973775929980767287201616624009199540264960*z4^2*z5+26505030604933744267023351357834509229239401902294498527715492369711872148482078140412354615493465507762083267502794847527442527905161240659128800391321085427650707138853480891148044421254400*z5*z10^2+41060255586537277569637039129869326231236999190597783702053529544602934507807438071055185997909157994797663223233219335350244219616991457296677953357844014214832160963400869190374680154817650*z6*z10^2-1199469253535005369054638320177811154482335987335882686332557888513958084401425457312010671519390941239570948929836284002481768493918958501383981453542339235422710933291271397464384018271015000*z9*z10^2+197299227993263663162563639047509201128598928109463104390423408272143917871810931679362162249515970025671972409152189316420268022372642347548561812990555280142126422606982444077208765937200859375*z10^3-337890034593846992476553936214910129808557627572616230465094252692091318036891204307980695748601858965566183907319187282425446850591192416839435763620276833308857009403986404056062081584*z2^2+29909920852197255889389476995186940933059665267067791106682675128529000702095857558820712645989304476466637264601362230669854270115216382983470885613630798440716992813360260021608362070*z4^2+75451637110893502712671580396192195955070388588455529271607302032738803589882958463134993944171093290714589210559765144129254070788457682123845779984837631282853237418559471733333833464*z2*z5+30573996594922495553337963219990581525693058771815719802638197472485118908775113469376941649493820198082336276479210307567194596756588602842238900100313727068735720300781413303704348590*z5^2+83528003689057052841501695864421414607711670794307298634667979246461378479184881955304097040369641313634921540264496372921969710547393067344898315560891020545593022216164239549303999488*z2*z6-32486905210647126068074593055373530082719694230457866409594988026542838343885505216921812878338883232967107727326216424098959575983524381286068089426788994816302209989634984403224527392*z5*z6-25361900684205357172787450613039863120147888759989472393558439415397283265936542625807472963423886045326681249009949388604792316981610686180459050737605666491180213192972207674703655638*z6^2-84326508285792252163158771285909441239323954884042680151360851068997186507480851177841362491796158909236661025841956418398046144247024673174345416826409288766614494751065954574201658624*z2*z9-43111397810197451120272316085075744924329468173534170122556020453183280877087615493783488024379638759097543496303029267460412892416531419279536528332481868133165274771517639561686985344*z5*z9-94376620361817521555257431965015321203334105223586046295698019503776957965353418325750438408508906765708797374590963898265332347407786593945899199064509724598907741607074387286100761216*z6*z9-1676499983111543595043723770664139169000922092758488002843726581752689632573746446409825302685296964301553360527837135044651580079550280009734607998285060501583069164861602938880000*z9^2-981547372633727270836683758237943151461826860833536216157582465396936409565152235568750318959689553019853943117624488912352630477362574459671286203398976737501863773585603453367085848961696*z2*z10+252052125666116123306586832172619063313366122854913839031659358797441299393823920576372712988412753664650595647849554536324181499339745371350296759040968657811264886115074060958916327872188*z5*z10+658432158802903877392588359940245989522992889235153845508353714092299125285195263537003547086106375444975560818610574791947496146682964047774147257936341217663028966120946745643560791884952*z6*z10-11425962474733415848049312626886321474709181755386202658109381126563533525951849050937858403067456742302616115454802612998097611568871334086903466425323008307569270598660154760880720500506800*z9*z10+3287251420348826736375929379969207695529899865193372129103457856015637919807445315321448883343612515720529688216195829593676557613635795651581042350693378022857041390154658872162445957382487000*z10^2-5225615115599430955262629293925654690659488518823417811062672053891404821031946565178955194530229592856738093399454858951188982043537342887630930450837807588220940825130743285993572750080*z2+765903509495806630647891991173661140220272968513080154267647805276599872657419619409534165378723346733954923141541469007050426766386743560659708731822743087726328558587674353929616860388*z5+2372826844650249499408426695556783241809098391179704142076084534416602436046361004348816342189105775325382685504728213545840214939111749615777980023148109092190938146163000282670897764390*z6-27163035138991552411781258819308065871256756409805079404217765772182072112967642910043439954812525230600430673606497441246854415729251417596599434887229866075248444508640392133677504380632*z9+20195588715673218880426110420090502309468049422540971134446748163942906006357072331672253637377135857251173997195679196075516658367232136024771679468777737373036181597853653935119218469734815*z10+48748934273377907635582745421138055821226886857594084142873368544505729127272894317853616412586182401431799657688334477247188594976175238230379337892971678059526840051555060947886485731052, 12139254788980533076671390130271598912844434252362714149922240794714799214450862579747175558725678990342581571392300*z2*z4*z5+1872725233425743119242244198639072823696782650164211365775981876974395727482767813173232625154481767345132548870335379350*z4*z5*z10-1031719874516157631546682510888950829008615416708268495169544467847927770343262985682280938359962756926863714960314671600*z1*z6*z10-843443260752907844779604018229566657578815430724302911341135896819120431688086742957134046825104721210360928674494288525*z3*z6*z10+2092428347473814809902021329652926725718186849694615959061602412424545165187642781596194799680548029849436139184577624100*z4*z6*z10+19435504011420828026253160453649956825546945791315034430774733663231298617538583886476244485390801487106109902542167160000*z1*z9*z10-29368753720479244773036853314595806509376809555549298234094998583109012171088713088072495199249781700106310027005475063400*z3*z9*z10+10079342597443551653709794341969756556014068917573417649478432789231366767541491653373629322241795502084456806983010485000*z4*z9*z10-1019691422794076678617046216376559238637316614173793373496161117994243315475163240294623689559276186395967796104682645781250*z1*z10^2+1587011960320417542432894520359106477182848717991625930113546208366437539563905061165024827063749774990797008979817186953125*z3*z10^2-2892086885157298756633790001273098180580794654829568624833744166209273766718235709432214497503537803489147459716346899910625*z4*z10^2-2974841279694702846597503217235661013915681569587243616903918931718358963281207560870570243732610381613196909415754400*z1*z2+13591735641796506853442459318774051194151791588752811838172435019286069947341462260889272153750466602483839485983823188*z2*z3-9183702210797394510064475891615542841742684175833425441257117211810828665895133927479363206395036797395379774067515944*z2*z4+3371647033314865384340533039964967770755582034068820727235464175899352701933213326498621529879693303198867525632747972*z1*z5+2534920364482065792807142223238242448874538504138573282867295473740966229593449983288965890391669904215051185542599472*z3*z5+2314621318904994053935327014460964894337942067388038336506885614031783932634964950761857741577322885676389395311702650*z4*z5-1853701315836565171106608584819901993505733497896660103048015366373374212840521201299103993079468486378440861530714428*z1*z6-10405843287755006499338714843861936387344001512795568783271619991359865034517529511315937651358401030185203445703569122*z3*z6+12793901479249910576230505629898144809634447763927044830320243362439656076405454606048892840378420443856040104625314372*z4*z6+88646324069664402529516595156917722975962243625518855907599282713254923663514478659272852373424728861041545969842436800*z1*z9-133842357948148453775903758557838950761588780309004491365765367680522687309832239267382292486565481611762143889549821000*z3*z9+45848038168457830433790978817886368391419589384378303820157190679260531247171858886045903951559264618197924237933703400*z4*z9-3722325259391138198768413795882712059145001902754566354030944545716273337032237589207210428972345536201460347735923828600*z1*z10+5686752883042251773928058692175687748712821548076338127350356066017875977279829278136599943463689181700158670112091167950*z3*z10-17545650539091140997128094434009869745878586862262399116869266843633745215188422613103387202896696223426110964874929553750*z4*z10+7732601801062176359026391918965661209647225834223928000127521286990712313064817275249041248264471378778084314471675050*z1+15278995941695581286227086350628633285056210594599402463605585141155725481339450814431643003580955712629968717319697613*z3-47061537957245707580566708842884001491877926496461862846806358993983679550993255254165034289604023694880527249603565369*z4, 717163382603515940771390254787226797375460974594242984590309393630326839080350172850551097688941821057731091474567692323534324977412738898781973775929980767287201616624009199540264960*z1*z4*z5-97483099018709784120223995443271574539028177101767102910677835836718433440216214951301761781220311634193541230425494151016293241862820534165957938196550191066989318119811842674374999854598400*z5*z10^2-57799834682156614243969931590881933254619244183364264789852227088743687304247623341049534939998737482109227489858043030976746195807907680660227833395196634285552761106355625976921852062183650*z6*z10^2+2658070282417194722435402358436820867313456475728428057598006089625445416793090803297147456168510092238858990242156270996325471639613854473737809213438120625591868077902659032361719930111215000*z9*z10^2-844199380341587982366028618902540485129097689190634455692119899534497708793839105233665591822151356374917077784953582158572288304698377537361487952595287809518147347860452222818390059514321984375*z10^3-365778604324161822134733965697602936478433855833756049310940146245112311436747009617046830004421050994601959177976795907208215282462139857735823065881709961086946865183237268450059497296*z2^2+2868653530414063763085561019148907189501843898376971938361237574521307356321400691402204390755767284230924365898270769294137299909650955595127895103719923069148806466496036798161059840*z1*z4-166741941150018195651739858778958011570900394342560685399722204093536879123954527866363393185771660050886928436892529698673227887490509095436983067049943013141021948897322633356235722150*z4^2+94608999172784760537027315342054878558321723616320759269053594558366137321077222481233223742320623768284644306100386305536762344714609940987286398158919227340828696800418629108039571656*z2*z5-160116162235937988980948198568873090119758519244992421372631392708090105748086141547504538750608632772543399431083072279084632197713255298203956208571262625482360324729828249637264583230*z5^2-156055351219172749658818079781152847178841461836672003574066099477159294590285043508941053902356189076076102401306854845426194712797807612883453243485200969102907409277411441122669568*z2*z6-47049503501145104707588300313245121461404075252956733887411145584376121806974134771589827928317219017367134103010243620018756686909601748232158516453540863221747342209758970142354517728*z5*z6+165727676287134028333544318974531363353416175173349027199879833905707271823036361520436405605386853742308646863554515293503704753032480951230218981924055902033809281218753027975749319718*z6^2-175341801383840390785722538766227631464216682745320706581782265519686370391862960739054133873222393828920470563166827232149755373358939671021040932421588328944075731584620174940244462336*z2*z9-90522036076348200315060398768404701932582524839816635726370300378612551870090148500598049204458602698344477225404129322104731026442491023495311823462968823525648345870356625176200784256*z5*z9-194153626896991673551726714268577818959542027928376434442703802664876397743939482535429177926177434480261584166603916630103978056351324017928173876400311697561764936000605086097042667904*z6*z9-3453840158367291733778713370863520342868138987594801833894668213105701865744043530385505092754816415537666492209189714813749219859123467980540317294211781996998077568828965765120000*z9^2+105737775743858571514276986002509369601643083708544053336944172858405733071920782897504445824045335494095067233215070737952507369351551749901370297052313412012200876181483803691515294797216*z2*z10-682219876131606793555011931771421207553758660300649732898999883680195959753907542295327255070759347997223665364426428280673320270500371907977984547377831756228945979708814041325919609458908*z5*z10-493946412067997901761249723868139255470043469271645001156838488549597109675004248242670797417053716659524367763093572455342355929778573949914479077626928047762919114560229526085255503391192*z6*z10+22255251217973520519406958212891426828377152366043191771714099605264170870369423194621574236722671046195757624313583120334906355196852549494406360154987256316579069380997556853545589725866800*z9*z10-14587720942508788356585649162728594838741122747444642332920941813600351159498958161586461920944262067737070748956294938130388691469792190648043332794795750858742072133153380843430180939145519000*z10^2-930121966386925522752070334482986904034033839250218051797817819623432832930035867872580744008731561817410745566455442477538190113832501446141554891033025129152261930681298037628336477440*z2-1017578805607065567404076851970317054599505014209965538150071394493800908383946163409389898717120297495522987911437973017933434229655320600983950841349536968408136640524398752174245152708*z5-549370609322900960370951946430051403333142963623037025214570382760794231070264124008445339262468006294702094704045032089689215328045831954660315847835233434982521366327479846861469113590*z6+46254774642423773216958013121886485888813497265674376853355041340370689346392368122234398532477304420779770267873732691945574403419533504995306535564610175594405377897210749522548654440472*z9-96134300470100064636144225352494451690199420270870860758434509871427588157070752443058023694326228334281693985906271627181329722172076214331524223678566522724642807508987461455288081267692455*z10-250860460573080642499065964324102943043859170439461309301505741621747379271186904697010355547832297188783063004071091132946202842822632556771131771847008782332572560251639195526151701696012, 84974783522863731536699730911901192389911039766538999049455685563003594501156038058230228911079752932398070999746100*z2*z3*z5+13265775584208134207092016278136387491784682436854395281631280426964906952200620841746395210903382038411946190364366134950*z4*z5*z10-7257343756313411659920537128793330052522930766186078568955397437771735977444683862316133162845913491557872105683450028400*z1*z6*z10-5933187117876496719744049171040691992299432275084096768013396662355166269683697607069999087858300770933237880977140859275*z3*z6*z10+14785588207994021482401670452249523983351724176253942438723939218072426827039203532691134467143739508715123970717841257200*z4*z6*z10+136836347672062323698271572854544320278820754483889130846926530375939306546647698745699718618932118346739065247967713620000*z1*z9*z10-207283338495654105238811604587122950870586995260643018728042031807992497417535837926698011742109591380126418757327254073700*z3*z9*z10+71466790078841104595375958458585707281956364790796631761674568198078708493408765414760303652632210451681180764335735322500*z4*z9*z10-7107723461400605388788186371258055178867430159541629710336372634806218995834511347859230746332797028222039802903434877187500*z1*z10^2+10954927144666209557314567756503860793517142472321962383728309757849139948541856003737092324001411837442569355155827730234375*z3*z10^2-20366880506925693221170772980697070535466640439775116677310373034111540933156616050829218065262851508055454994884219717019375*z4*z10^2-21115345824139130153083742612325695981718434834064877291868069813200554855601864388896067601945964416128607779555821200*z1*z2+96556102850235653871762348403192734662421107968133428260942119909525353066335696220780266977696498854967991782905093564*z2*z3-64898466192156474630956240690785655582548548201744521288282794457479433283592790946269142299331875817881886689246977232*z2*z4+23947742233463663613666844575456277017253338371373885618644563414336917867585293323332322931364649726837579403237221066*z1*z5+17841602575553671979863007953510966451814843817693866280361357381535066721508132720561126745828454992497065080783424966*z3*z5+16446432181760282637499285557850446151285203255071850425588458411500950132251240343850747677789560251852757844023131150*z4*z5-12731026674219677763597965668972362833026558748844580129058725804602853283695714744101393342815481823785152467050197984*z1*z6-73575816225860799696418498058050905540236814488679846963652061671559781690389813100649903333316336861109890248217276941*z3*z6+90232583832522089690211413478788547291604991638042388725039227985050018282987117412084185173411482925917361847358995616*z4*z6+623981367258826551610813960088246122457989736028700866733627073384323329842387102318786788643583583799800315059868797600*z1*z9-944442434436233040210025165365292906654069670803997760642726373767466943548749701495660588335605300129321413124970716900*z3*z9+325012388214497410032581459894880179390532736330114328216503395079822366031974457568827441825934506021509587787430189700*z4*z9-25598117346581172696181979259267039140192470087049323582568814409805462727362550915655730457891284443515451580632083360150*z1*z10+37524351098897938824357581915325440747441424915994231496967026461878270733773382916393171437545695613983040327634243038900*z3*z10-122842122646186844953282147005184977221965000860426104543109984280354685974781025565650014111492099110565369252139116207250*z4*z10+55681495900561799714359284138978175434284175340568169964721166839143452130165120370477366503344541624245496144856709750*z1+101729740494655962399915259364252982774298766115296361118981022005870017162839419099396124242237147683476780930504025289*z3-329127844533761025659926775804518630989559428525843342837204817408717569119276790050609693968931925055117688931894649607*z4, 5602838926589968287276486365525209354495788864017523317111792137736928430315235725394930450694857977013524152145060096277611913886037022646734170124452974744431262629875071871408320*z1*z3*z5+978101910242435817802675255008623898268907855958289611685455249037387418030138072180568898524061937077824991875555440677729327441368103121165099348353662473951343231070620963897440075117400*z5*z10^2+1747001039205032429433211541198345124633955403002499373208398619509764886759562778063141645514669023474827354077209906346133911050840710116736993657950188780256159342433237852932286519188900*z6*z10^2+10906239949719313309591415608168497051567470593631204478485015907480289628930790828357954191551117828998853556248559163785959722873624781133959379214488307653782081211760617441357074309635000*z9*z10^2+3133422333853717523322787784146996871880641472564950872110817144715886756069755369365336598967484461917549100686848484768365696275456373635369571578179880145927575581635077446571599634949640625*z10^3+102172910981425689545615913338991677900877621627984160329175200069099479911122191265155325072899542804051873132302270560730568448803632834197867304857767566166485262481707209189999616*z2^2+22411355706359873149105945462100837417983155456070093268447168550947713721260942901579721802779431908054096608580240385110447655544148090586936680497811898977725050519500287485633280*z1*z3-1299491690452546451339505601414891373306196974392573596830652078700929187127572548295420925338736544807766775070298877066911752813013895161072534908918382326054914072994394765709598750*z4^2-2663859571769125744866885725212530360445835172100979825546024610383938321497815560754310174919507224045382450210361511038782577615866769163484283276924933561318168084309748097778692096*z2*z5-1351440342143569275696459423010071660184864906093278027943007414971823004377828836819447801180339555147802969750158365061708105803442515121972366748763633459398756907115314223747164310*z5^2+3502785159417715680900578998590156882705806377464958973812274404611062245668400876204590852170862893679596243620143645690441852699295674045389567602464432126492069755029785009169599488*z2*z6+1404760457348146067356223582299193965333178257982195584780657115103103168580391028754566799452536537391391588383408159223600643757768663972437141183392524695185216536634661348234894528*z5*z6+1556711942428514566323530860711504523945031196128662314401540320073780346819777732167882380318577103100335567800831259049531315206108820930571551803966272597961046544777619516637001502*z6^2+7679646984088704190906248237307695906677531885487056902255798179652826065144423215089349170882091504979003982107481919881093180002321485980677716584598017996790598268917736038545828096*z2*z9+6898522536892859433377398308600377258984645210773128978208981762896025316375838910548352508572058657702191219020165654007584821365298131134899110717541182491149611275052264123027878016*z5*z9+14055633523348278686061960709962683036044869482906489231194513393083307769699835325817524373321540663132641323672066515915765100688307390712149487279376723521754813336010809366150742144*z6*z9+227718849937012118601533501862917962146819373963195550091481913496946015659547147080254792421473101150733276191332867310725925073568705071043442097387273371411483501231843000320000*z9^2-40506379657507734026215633535382988318474859005731886771757672709681719191883793619400327016074437927965838859563147302500826512319442727496401032958954487398430940531025094542572649668976*z2*z10+5323319683221287203441692845127328664108384653003070525071525268828680550234141914287960228424224136471923217767641204764945953817172453348746847845929331873980123562673642024043206165488*z5*z10+27563785399990014927016661446819694874151320317794955295054876563252928696058870376393032025237245666065570977439962143758180887378313535228083832557975059424982001170295345713310856887312*z6*z10+124481942195470868081055162291322553106584012736967989716995676561672478843736002661029708650736305144664535491304307366773785877622538322326866263458475929258707406745798482817066606105200*z9*z10+14013620666576468682146828970241609188990489318090239665173099891793972083693631016541348631007876855686414139192942755843219396067020829895720654266996579866817583168708660682057148612189625*z10^2-180888875780538745233798602725540151333849713557849605521753512168672083414331027534017675085256499565981101387484687712421057507486871279656853486541807355033711539568977362008983568880*z2+6875816835998357265760234626354051455427723174705552476495873987369424297134687612376441865269331371031095206155528250262997846796205310588720511892062397792139546142274545758675567368*z5+87361872119239894798753095459401250165268764744729840583262820555885972672511430518297139890197124794720155909726119285392997781878103255449947778928772394305191267796424441112702056540*z6+347609713680870452875403947290213827394155801604469906547100815933411790220727729619456809377901508215832542613087765452397025835790354243409457903991254838067625917220009511407435639608*z9-197993356224464000633455636954631978374259120190397694843220985419933833587579645301676773971642714588515264212608056081870962815881189544731239011576126695692526407575247805906620340046445*z10-1160009415539637572487531379246337779222495218879465902599413030371095556925735671169267736038277564254013191575805243260209929211873512745009846575541114694938696834112140636323008968083, 249015063403998590545621616245564860199812838400778814093857428343863485791788254461996908919771465645045517873113782056782751728268312117632629783309021099752500561327780972062592*z2^2*z5-413296054766362532428362331756326340373058448465291855434531735851984907515644160247230649472893780851642593968869833854442608283407742750011589635328684352974214259621628837583630452200*z5*z10^2-887332542081777470607038418564741068684708143216472189476157651657987863228028245498645078775178164548704057030785800496153176441989837622204187470573806693870393751839157512659178479850*z6*z10^2+19568008052639815731388288430907036866470534621490423447098155319476939280039886435807710437728744666522557703392818103902904205404001545178160479736703216945713098896849837463437499955000*z9*z10^2-3000691922391218817997248531723447854132810938164942033689205876090960703530484855537135066852878924306239032443988216509850090870828684603381641874965325447404952379831205726255388822584375*z10^3-66256087401259787132994835393070727212057849827551440116628013109230803342037999436375066156492866122234566060643231102458570563902010229940352727954536273937626491119262976128272*z2^2+164593276471245824071746049812898942893459425982835821983497886424869168676294259832396482523917631753815885296869678480769579725545369045059721134026250169830309808463846146826106*z4^2+790470279860549070811051534911200296827955713566796749538146959631376517691651260504177477745015045411571630319154615123831797107120352593072506769423373679622224122844216369345320*z2*z5+299689353744242149391249577793289943992572652545888714843817146199233754584570719916005532776479425629854027946462435727648281854360910983093268154845955195587238745544223392654178*z5^2-527159017938135867883466854920282521328983843415868525757411225882061262858582247460213268552893165693822871251161805945751786263328361573281267922049360933538436984810427971437568*z2*z6-325058936014850431112426452396408439313922517007016200754311152004889274291589142526078754514851251642585675226628101915735163950352732102869942708253215956377071553118256255759456*z5*z6-281593966007574698971967683413385623007588794404812078942632031023427578392572631055991649567108663378383297619357400569108074253728124700637221394122970852258814095420743421699834*z6^2-1101299426383530540335241492112060355370084110847256834690333990186278035145460010174831113225375486097995158096475841503159450683528400912230606182690157905381553992634162052009728*z2*z9-571796788851544304901806208734999735528195696549014637970480537237532984943223954493029607415884606803876681662147916925825979625821477164890746123244525925777442321337557836299136*z5*z9-1244652600926843348053131476494863469111973294001739639181541846371606099998200420261229859728746664387449575253425519807636670565274556765608643684079104027079706722962973875506048*z6*z9-21819593384253076750594101337255058412357346252025769409976825062314993844660529353855382110872560540231986216684662391201935220900364215665797345655899218161877993202565120000*z9^2+18447226637286908937203257436456983502869779818673616495957209688715784861333653246732169965514539124554567998823803061804999999014842449093891138411338320340617270643216211214213721760*z2*z10-2013794920314718364782637153937139944446327711365205741481725090453282978400384545722713928726161956905313951454588158647488796647094569298322655935951529655893983980387752510886423612*z5*z10-13479780161492155044357021044117056006509492393056626124672273188212301478087090673096557882473752260587901569469035537256444099726155538342954909345669125632445717982735462159809390520*z6*z10+165521323968098240119015193899605646500294273800472396147806124441834800581692704687177848805117327594372829407781981370848677251674321478892720865577299552953594737657286017759663666800*z9*z10-34708860000838441352546104924242362426726328030973394443184434975864052762236172708782571134279021846711015395123634969639523550231143657028575919587058986788320538260015058187935286640900*z10^2+81452219070886546990715782459595858527533029186005256473953601346361755789549872595371669678001756366911499323700477764808072566358986244364787366050184386284311305685195847052063360*z2-1011722327662704843613502122743783919006832259578392295109962248301183272020321534231980550641718072420542136686533833043159837046333048533579861563796488535222481447826144904635708*z5-41828215429351245042220955320784193113989717535895403530238481595095529329308022928094767763667911396755931071804370129372850496908653172217703449189270810267094292447005825341725710*z6+348162501781555428377536052564005255647861604838705713042012419859164172394541404452504124938778111871075592856128949097031284788866246035190789141440351841741698509814052230052001720*z9-109726011272597151725003947981692951596086696259660269393920513533841614696824214821260690616975241713910830606705308644414399179492454378389823287173952806413230697432047475306059353343*z10-32472553759704826522364270559339306670108826433441522701199123829575299409081569888393658040722772531250847597715109504038454120123208278546855922959647421161907118734060210141644440, 3398991340914549261467989236476047695596441590661559961978227422520143780046241522329209156443190117295922839989844*z1*z2*z5+531413008172105661691147859127172816145338614120792492743690968510594367248472825561165449295084698776442197467476615947*z4*z5*z10-293605072766590176200246619569753474500618846002911797803321900290617320932641731720135371086300142452580929985394601008*z1*z6*z10-241139810800109791824994380303135778387008107711344789815065897223735248786244429882606073370091585087300646982937041199*z3*z6*z10+595249169160010445651810315235264507849830713903473176579153630932112287502591702223988832603274096794355243252569222094*z4*z6*z10+5522239302242312991767518390130595934200555001184036084085812917594521169052676249547110865232924401985144063709163034400*z1*z9*z10-8383810248384329722726520553302820959858072751155619562696180811035049791523573716675565147118078613614254409200738183556*z3*z9*z10+2904376689950876782520448490343341666219027587504340320847313922403494722117704878719239878085314467049667252158879372900*z4*z9*z10-292889756320012774672338744767223699730664995480253817658824606292446929945180844816105140530082020894633846147927708912500*z1*z10^2+455087832219303254857514925378325168863276902821222830415078836802335345909516402906912833169267606099779538562657075021875*z3*z10^2-816627799693025526957245454585745002860788905629277845998176145483122063820004420032193522248037865709562148660456536884875*z4*z10^2-857188008856755288969835167976827689943796615748602116750390710689547910035122269830684930830525199670959141043732696*z1*z2+3842601929399203665909240082569528755994314522247973630830227059904452645236087529840395841054017419870279676788418224*z2*z3-2593700970350687752490335511253834157385313179145385966089272430920702497707206464816352918769510897228770986800166324*z2*z4+952404092143071667200228438927480105351032128496077197181490043637780203328040566686416990653402683474738660296141870*z1*z5+720346183872868362512042080974844826302487009758832675043230742717590147019452846303748070580485193534647612449581996*z3*z5+660293707775329717926188392007549627948193574960638607849641367073972018442368629634783257242609188497964442132662697*z4*z5-527918102485038780849084969910046489874530489113113873594685964128054514220843007724365684422835328154253307714691538*z1*z6-2957568682393721907224983349859097389345950371453468124367424222342230332502570891705644055158959674869520289905289913*z3*z6+3637165567514024683792557476808463177660667281966034307097181286389061347715818593366363351734057130208037228949117934*z4*z6+25205387001214280128703466609345772555508101016460158400766088924760012699249465636680619421241898103100000048276367264*z1*z9-38228771774190791880837719612960253643827213110011749227697686110664322615126608408325853469831856555235401950914136772*z3*z9+13214423835871171735861888753711701623751437823395317562956237518030154383492052568963307834303278608976020826166362916*z4*z9-1083904253165830508078776909157590075938123221572162266054234480754068076049692761443698669067359618573461186280400763318*z1*z10+1682336014013561807032095760261109164739875696925915077533332582671786460033346659977194367568266622593005816886978957980*z3*z10-4968930523231920141580975869549868765232341360354729477275329837615709145853573771254952252171686835810682171990428640714*z4*z10+2139025467528040190885555923788130338624882244646600978691353785158662089613617456618985577546720400042787955780562158*z1+4547753371776224305289388832145434392264405944025600863738527399914019071744303388568383000135191757925948652507795221*z3-13393884011895744845672586105065471648189774051847359384697792179723992809307672340909155288893919589514935211415603843*z4, 43507089163706230546790262226893410503634452360467967513321311008257840384591891485813877202472833501387812351870003200*z4^3+2444235997225485603181224425054582688866671001876808126254145619884467722497742716571002338518637977160301109379133357789675*z4*z5*z10-206466746731196038733049727863197054214131321358162479368961078088459848079444321842071822692740907918067108277874381411600*z1*z6*z10-211658029369460095596707117440515511770787691635282076353020561458436499759848719312177329389097829666789193507968407761000*z3*z6*z10+2115315644994091913484097663908518881115788646940486506747730914218408304441541809153803664994099096484562406196560164299650*z4*z6*z10+4774996705094576921036843356335293986112520492183896036113224584323828847963699111376598146019839641501686054303151679840000*z1*z9*z10-21096032443853351675687761784460348851903158410069706603028740454247942661389278749264297059588879134641957252792942243101600*z3*z9*z10+16487914236739607615679346587022241819318988246260198244212659636000178661854672831025886995423417328167651742373354625540000*z4*z9*z10+609608522621912636730448560472455279356965680133377984749243292344402274340625842564541018370158249452549237410855308905078125*z1*z10^2-2550535342971144942493329959958762152861668542302296993179596377720059515666250053585712207553682408160502090479238868301093750*z3*z10^2+542113216774734822278669281044047013027182334042027827923462115108263217512093120439275257639734391079854735552763614050975625*z4*z10^2-7651677534595375778172388432761400460694288869967431001685597480700490584836362109144509989517027084344090519264467551000*z1*z2+15919270656647240694133699715934092023428210141095835788598101636084908076098031873232087655070933974604655792684643584916*z2*z3-7313343782179994154350010431800139704601916057625891086956613822571580229038257696526958698270105194906041003050748990908*z2*z4+4982618414235841558800040193908721021898391663396667064769129339246900616909063591493972350741032421522951148231790171804*z1*z5+4381460623519923405268304043422632464586800933801297974307319559174620258885543268810833730368639401954705599169285557554*z3*z5+1545674466402119627302245810446682897266376949390632250212022407600063762470316806084511779055493092930154132434626999325*z4*z5+6452609060225880574300872172818164557538563219509217681840657816900143729172265471506833743519407298809720690766909811154*z1*z6-5859374425928355911685292622325234962098376456434969793957124093355549796918651631308453518993893214675655938117028692354*z3*z6+6556513764797009616860978658875842777241133958763936392968161343094817119965418884735228985210810863906795533894410709554*z4*z6+23532378985608442840027458423576252386242883631106472787065379520366359724950533488048022821977455692398483090779858860800*z1*z9-97272143728000590719469712052619015626134170416879262174445010858529459958532271297391795254294285146761582018112985405600*z3*z9+74484505411304891595419385007875868047694462429692417894983546691247946939465456104806641679307838139784120434041765949600*z4*z9+6543046704299085316767655492090013240828252750713058839726194558602098911676627082403022615965276937733228144046380584792650*z1*z10-30949985602644647579069706319830781636279416815228362563313116843857740801452913292185767434412000413983886800866525274286100*z3*z10+17604445420063337936741892702652860378398304411133231061302661200499014934494338336769592995211199140537480778751736028230550*z4*z10+16205987257584766781878082579760465417249129605760223800278327468885583600318127048301084842547628911156377667993749500525*z1-74294602753551052539943591049907129413486998932040595627702740251434591194018894259615366521027883225751410901316602170234*z3+64732693273564287052851354669718577130324798011105870702786433771006587490787652444027230652239664823125499345380864270617*z4, 11952723043391932346189837579787113289591016243237383076505156560505447318005836214175851628149030350962184857909461538725572082956878981646366229598833012788120026943733486659004416*z2*z4^2-537335510060071786600757494298470620994791343074751525603865947141592860950432612037235031696537695456830164343244209462324348354073902051527299705394585924598071374524640975175075997684800*z5*z10^2-956295069390828581375560264392209833253102218013287140776641716859266110801850197243717334662552440028384497693464444357906981339566132439751643697961855082376334538137809742601165571011250*z6*z10^2+9414829117702309346502390805942751183141056820616438744196658318214239010228614543918774854601373279736196770245767307325085403945038694243473632445700853592149261201300993820122269445785000*z9*z10^2-4799733904712561140190334887884280743573472061592781809055048062204664175706010913132806445124054744969977604592409308351959860656052121566276859552501998792877895637509315550277676920829690625*z10^3+1517149850636904811743876718023510254738549643902856589837906792973697394293677627752027970258194360711986413026586427506732861608665571794634589695451592395298173860997981008235728496*z2^2-458131287226422063814354932526110401273379888416575987267437428653533083321714639056862160826620884657006402400380621994058725510178672406239812587507637103395842576443104846728633018*z4^2+59889730989140429155872257705621461147539574620984719403566402671496153210283994204552479611290520664949724322027538188194105876319901798101305575604199050864780237369506935072950568*z2*z5-441479844380229267160903096984740746924490750089031796894387574646730011941296214788328289553225544128272989578581064353650357644193086498865980907476747170127290595734081543487052834*z5^2-1264637020473301720525904091274711176809996134308701286231831970430376465432615613764146376333815734761452877139533669216281240679740132313381957711511226892146934867526714650763966944*z2*z6-100004378322105820319778415066302830782599240273624899224748312043041469150882833206011428473289144757487996506328535269156044745592552045133059852870369055307486182441168107410361952*z5*z6+353746551707387398132897253206596605108655992592805177259736379651088323836519706255912339363430264880420300023646539847602626001859380041059715512031461773139254862998156339348716858*z6^2-1547032291954971337878782406192264423831205378349615690938196123561672093307110682105723124069602201910871436003128570658485425432009397743796064304875389919823824997485885785286394112*z2*z9-1696428306471783009726074301155138512151370466343983069304589627279084474798408795368989940754431735464445718402027491891833594536276486494768423922265685669282725290252226955941506176*z5*z9-3383360256937187667525133433072873958279561806118827465595596025769832860685904869541091107174366045887421923645536238959436361421123904508693620095004101167822079957305114296944442496*z6*z9-53581862907731862408737878493975879411077617135264508164178468088836239789777356502521785273553938568672573597789848961187246279582867929622976130757361419454475106305101086720000*z9^2+19883652530547104696847607837059895389210255653358722456211845082543590306361832398304948747985639881161109268393917116874253775663431892014721161819869354966255383023054975088524390871968*z2*z10-3534251390750089844736093951016685936592408802426801635211210431070986858487561554954195431160699200008284794039409634789707728239880651903445069797065210815323215392189564036217933788900*z5*z10-14192866016729668757747133188836234605378528970229772326386481203675321824754920848747216835469116227826251451074843185795681594306371052816930416235077548663051884737036936697687868765816*z6*z10+82492700950375405084055152934536130656872144781224291158373685001865316987485815975005535368341140407816865277487697563386417691663009820702374031393615718440664778313733318208426112830800*z9*z10-71748334328259208323430098697847280373344959330707269684847196752253872743364190238627812487541028180629460437690180252766562428390313750269107119195908976468625026933049182805809400394614950*z10^2+93109435250304855117412788868120532009004774830229437333616482085730137079289032470607238898378029331519015946561448057678136363592434943721675655574273122360947285883375173919411891072*z2-5713662680262674922972951667666303536589576260496204198174185299958017836247319112553687248691928147298470175775502290588555476091666581385797939330510620386655481830045385072784808740*z5-44238932165627332453028200750032277097779453539726924421568041463318459874555677143346118945024786019561020414011150184886537077535776940092690417979668480573724355094460509623332195686*z6+178378062044282437878456718118749884718113847308522256746317069183757787627922655530643862238408212855217854941628072303896969703302909304374267214479993022251815640724107659855047042856*z9-394775738686518682303480073576695133897452579820944443393327649629570056328921553096998778359829326211418674680164312955884692413063774118105878728472342768829378922091683350285818688504749*z10-864039107028466399712052489998030526963806437364710704606959514318873666949944347602366884769937295379588295395939852456948651766476349337674954356791498583392502432490159598658235613410, 43507089163706230546790262226893410503634452360467967513321311008257840384591891485813877202472833501387812351870003200*z1*z4^2+4809880775430317842100077752787470927168939215817025396617021472569242334620535341640878010659216710693668585674695628403975*z4*z5*z10+778059464068226519822317165419841879351325076201538127770879777800764419816730606494574002135252924432446337252624107234000*z1*z6*z10-56242547931246924082659039089656473788684274927603957545805101736382391529343416226488227334335613705025508104534142397000*z3*z6*z10+3425353027178124275139586021137312619408911046959530039585140288394207226800479837512109325027772906195687432716601881896650*z4*z6*z10-14329055873506581673539421023810966174859845407235868141391049698269837103259533372166480885402191816801038373561591724960000*z1*z9*z10-12186581228334278934814304762715136884281256537389397213161873265865944467586290731457169320294930237743680863778880910973600*z3*z9*z10+26736931953298744320837744642057707569066868562477489576334320430050397699952619700985817066933893970873356144692506563940000*z4*z9*z10+2167184441463232300373264498998527881351620686799436744047360429592456739898978928596489722686465773608832272010186047492890625*z1*z10^2-7024062107159386951924247692757300077145246563713948176146861203936821435901938277495284062982166421861888812852656640551718750*z3*z10^2+4290371362666717454756784906310095135670692735036406617037793898647111440374650574471579593010869689402595021277637373022868125*z4*z10^2-8163269027785018517388297086115624622741621031595013784619758172101403507617066394143153155352667472366863859253505156600*z1*z2+47207338107543492123295921970539923815977437400152916380306338060174710107758342394293983740077748831480230562613509742244*z2*z3-38533788708285469436323506526395728264033812281590642894825680624055360137469253288356609062154233672597792171524574881772*z2*z4+10781997064501133038718474140115149771473758085730159530110936184793217103062362683682706763842209386561374049243240012236*z1*z5+10288707541260138331773155952739855438345113897401908656348520812333595237589149057786789411659021373466690078969107589786*z3*z5+461116534931741971579828721274574196307256076384573118514301701410579181710597101153570403940826348055417378283831109025*z4*z5+18146132460696428970686967553223586754507934641662286702681082330417624486673256092031011118490220505142022163978971245786*z1*z6-13774131653667338330961521816675709214199871189906389965529057057579765490253559624173214985347492441927615490124496138186*z3*z6+13683814306998635239188747527582239302861863058942612149654732455827950398569147025232301280499995247545937522322862558586*z4*z6-60943498006218541811262195639380181836330839669677986050486175959948476944709703203195182289262165811938387684031686176000*z1*z9-58493749472855566604370313213651336386924116166329847125932858578216336345172115034611413798197698673336811413457745104800*z3*z9+120424805403339269637597461583873637367079272953801137480325576639343531350157447777760413577026988866630069314998249117600*z4*z9+19347899589374901774580270566758686855436074595516389132906168957136898411274481275582002733115839292159738144425820533595250*z1*z10-62588917528802925469892644702771437190673263317249538685365629360833112070850017660660144251077836707159462383896484202944100*z3*z10+45915038421819435863961398388169661690553467946755973704060501337682207707701831873693917736792669253623059397763264646635150*z4*z10+47566383841843984765375671307203959241409660433132609495289040135270168661421617278908613053870911601835225373727111132225*z1-97844629917538288046283317212225103298900879195808255916090215057344534872286317144305120125467287973611043289285992051506*z3+82699376486174738836329768642231715192223792322643996564514282979881636995443278683966495726201359501521795520011659402253*z4, 37766570454606102905199880405289418839960462118461777355313638028001597556069350248102323960479890192176920444331600*z2^2*z4+132315565718526108755258139215127624269084418701435237377667181097811110036233091460568061185402325287228521256625669125*z4*z5*z10-27975682030734609019197004549403998983124314364612770848892611150881598675429950828031618955989086704514655448482779200*z1*z6*z10-37904352041740073473391456196967760838423801734588060881079989205616586554830440525477058802419552995065869428526218500*z3*z6*z10+125645248998298063052778022210835958752858120649241546695223229377721692591176628189517283728367773227150088076616276350*z4*z6*z10+1238286167240046429081740104172488910674548446166624267302269508981944067204733070423000903791371306807379932921236560000*z1*z9*z10-2241804457594315469033340784962783252566687148428885177229772076209923259014473581695681466665439450668413102665191037200*z3*z9*z10+1011501166701484191820327601029266917826377989647952262756967083542588633761112640916136733617908126451871648652351690000*z4*z9*z10-6968150414410722936700685091958669604505257194023597105088925737255163271642472501748103396648577414108910168244543750000*z1*z10^2+54669883016893895272285481908959807724147012660342874775159670324097627338370966191146013403281934846483162558221786171875*z3*z10^2-85113367689887079607784935836420595779217158193501138010530913040846297104696630485495581415737173154231814220162249857500*z4*z10^2-301850439177415389373480715431303499073642494560457299391249934935214666394201424447374554991905830110840741713167400*z1*z2+1280522053621604355080778236869212588457807078734013446013504221528316360262234928853845354566913764155126926426668108*z2*z3-763043071268539122121827351836303831117204910968616882221434694938092277112980413281686056922600995015519411902820004*z2*z4+282683489065094236190815640020237976331653030747827459297949873540278991822244318604580419426175303683376031550309652*z1*z5+202676854469991187355264356376426414197627853883130093261272600949394520598538848964597228071452544448210526707053502*z3*z5+120651401190329522074818942525002924357018995119054018775583556417124563746161025481371082556881579200980676667964275*z4*z5+230006914107250778153794852488407438630932346606605115810506807274549679738192857423363457606640507821316334037972302*z1*z6-691606536472390394984979708270752537574001883624338108213122205317879850622406689372801823132661566335359612783757102*z3*z6+644197708990223029219820136443659576342759851651036100790049423298638191109722910294917287826870536667943788658589502*z4*z6+5628999355002479411892499891757907151823671707701445959989295230077015065054583894610352176014949551265870290521462400*z1*z9-10149870661889013338042376692650564303688163353263252080954020943725455771565107342843409820834358835160013887725216400*z3*z9+4556497660157148323976067008926079478459269235319632442784028422553086086880465462522076734203244092520940529704237200*z4*z9+127356498780679356234835129446541711920720915841433125834505171250407558709638086864692002118485254256996221661556901800*z1*z10+775006596538457837398201586504237725463929595607342132033377917421905599616176833374163599443555933135476072548066523550*z3*z10-940289331868624437511849603999242447713825135583884084988376469700413265131900526561417412211175290705884645113863317200*z4*z10+716189498230506429598429689506760777657524761893931126540216506747585690764315094286652498935018118320556123628358200*z1+3982687616644882130823335814310333532711277013873251045854499595665662972219191307319242345169686549158527605359606283*z3-4127631826612200901771623447169606791542629961155695616127869131213138659898119740332398975347954230865230885779210404*z4, 956217843471354587695187006382969063167281299458990646120412524840435785440466897134068130251922428076974788632756923098045766636550318531709298367906641023049602155498678932720353280*z1*z2*z4+459914495690194531764185772046922119499633884904363143518448807638683761317035659598684919055098917611451676663977950355498362052220144624744219449092763615681967885110357445540337420051200*z5*z10^2-67168729407594786718711116238431039227810798955922016172587861752790777749464100121146043463628043611277209151005591210766434169131995548294446091181837553247290303364362916882959301601098550*z6*z10^2-364346498735267300487125160499050556637782604426133809276102701934244194965543774197324300668157524346685078018021394060979814557742258194910575757783009739099623974440013238651026039744795000*z9*z10^2-100125917409575468576742990881742874952822219820191130558450934450860276181234261755582660880811671736827792048101166061988304728880546724902637661557168439105602369009299944540820169947914328125*z10^3+98034947417451649795836680260271218960821645968331458374396141291536084174611318131755386553659347983840410766153696439717630270311900695104011646516744110647785552304460107516120299408*z2^2-956217843471354587695187006382969063167281299458990646120412524840435785440466897134068130251922428076974788632756923098045766636550318531709298367906641023049602155498678932720353280*z1*z4+28257133401273053392303540865494827207532719578657992145382002937538089128672419814845669683853358639145865454009829208129139141286860008159679763358524463892743206637204212109222125470*z4^2-28102104594065354415736068060577651948057900604648034791869080562431418647570815568260428869373490777971777055892553364553001618814728487167034058888855462806919230379769583406280985448*z2*z5+28091622423141519539385359980284151205679238532399668075085463350220004520291797857031221736585703689776570942939865784854133438262775927803517827305485464114901097525264112440471569430*z5^2-34025983091531964728967665176784736132138315451769711903086967080799721574700758765529665827584190938428206142052755737727207459219410333588224371029359855587279699970328751755989054976*z2*z6+7255339444547212387595786880948996390990997597687923066233570556922554604913347300259509110017245203675951459121044575345954832561013802782424152747632245350143077331851768874834582624*z5*z6-39123350028534313680981761175179501033708172955083741222638722780603590750296111072568426144342340487080461505396843977185274244198254617257376292035812415455928813433608948560371810334*z6^2-99231273146424750482372464074833549873110255824009655903258298860029228913383414551093250375127175579458782761573977082640463139902261471496030524791331625400138044038615620472854583552*z2*z9-134698078055659195303668894740216440753257658200195169736528373709090049149989069953715223795096223129018951030090934459848409100531290708634694869642182886614587286504364125890843162752*z5*z9-265032476415865568160559029078078479897948167858726142656565041795084390338203087404224529213593165847552572175589074836274975972313705355922378835142725507609928997549700104264113694848*z6*z9-4108125133242672721840841890403901195771099284817671821158793312077783799537955271402168475680377861309153857810672102270410533295194674925730343252998527947488067907814206423040000*z9^2+1656751380953771709728713591123929909583681773548618743781201202210642221303101082526015972835280577060222078552175603497376628284586038831369827845074861401322704899922749965419162476342752*z2*z10+39441079868748401915922892786892698435164800518947046894204998445584624823941871712691557758048133441788608396894509255490019103208763535641176693327986612582201498923089792356028320988684*z5*z10-1136242991922212166163478001044754484459365849550304871460769483442169910552401970298393267802939916960402679819580558660001894306338998920978271464773356023073168680096832153523225795889224*z6*z10-3025508194168727478103241416900132760714953405096967860046577421163819725084557932813879803296688240883137323250834108223607792389195157851697394421138175635440189105969944311179208020124400*z9*z10-469304549389633228146458034970495413055482379937981487289014520521499864013035794984064348927175662981907043389395985094112201070790371674507808108234171327045639233459024739865110875081401000*z10^2+7794349459296924261467256873785516319651332191007236900676682162732022886744345131923295807695970209385264031581047911723046581092092086620186284153373422652910459973523287509967467823360*z2+138552480575272615118888620388001639198038898242654803782278659378176927749101213712817803941497771058219318023738413550456342279752275795217624414958833857097514727129430560484522726804*z5-3760623140210530515218781509438126828626980705205442464716431598970392114069133379940538013294541825506183772511074057263005902828038807147987383246738102723751573139863413036008281693970*z6-6423682925061275852550882251458409442025686354522224604655651567800471901504192748988165630894468644819050817989500055779806953386554564633569351579483881323460999446184931276172926426616*z9+4922696247906447447061947463309486370373277522443636243405301481116301489794039755214056377034367540033539947936214046017680668906387421498992086276812227385061155844993922961663281314755955*z10+28523507630581081863848638341995958160262916452364223494242708446827477565149025799306112349954767701949972349629848966338543464442906359747629924454999794693506453687894131997072467395036, 37766570454606102905199880405289418839960462118461777355313638028001597556069350248102323960479890192176920444331600*z2^2*z3+134679054915516079985037073752054929334181678552511351062005941560880333362466354425237860398830951817822908222787410500*z4*z5*z10-29576018661275437398841438317757577551894626475149291543300158697341848524770599532227147919427492345349210659283449600*z1*z6*z10-39215724336634470394442698720524093289443330865527897148512982034970152030831077301680002498315029659881497785216518000*z3*z6*z10+128527173738173017347592120868888742410671113836888888035436433258239319606008196122397030685142217014262262528840243800*z4*z6*z10+1268422913414263405290966605582104568037244782242213812108394801238239888700426169692241433336923598469537217012745280000*z1*z9*z10-2287507312903777985977590592386967155967118964910772312875822238144239845344093181634681317613206984157475513341872033600*z3*z9*z10+1027296398552343482963054912405374931742667202439533158419178059397236013747556908567591132631750704112116439757795720000*z4*z9*z10-8550123485660070604912783429999413744409226392790025340774612059912335035547974060511668518567652955476874423750943750000*z1*z10^2+57118178028695549707274512319633708948189008499059372406481852057135781545056244498048377395304420401483662236917423359375*z3*z10^2-89584405951055893004167319144576128926943558794335108610461272814040354280452452066555062435466800753946171366617946085000*z4*z10^2-312765653318664041046829960758676418914013448670102379539560256986764813246885261828478065869726759631812258672711200*z1*z2+1344459755046595736709669720024832254563437190591847056512053895934662102883711836533661767458853140212298742142608304*z2*z3-813836197746632116321304348181948696571765801642730570892064843368511353574150284461235553042648489219842142711212752*z2*z4+278440327556847413678628015106110235981304366451529962615974393021167580929941521780181306317659825769106559278029776*z1*z5+217583590846485138210472438152979576182256445854471348404227519270293912761887153050577011629509914806535504237884376*z3*z5+120334023355262415660699422312272657548982632977693406529553887529491839869949355528940501105036270775386907298268700*z4*z5+221325565117577973129900575640766414960454183459058029846227661757428951898164754941292928480575101892683765254437976*z1*z6-718745888244357195985760592995914409965045938367546416792172731334342222121550473969342144537897434106286930284201176*z3*z6+679217929294773017042888709323711250086070098117877501064751558306824799795562820964927528353353838662173142778572376*z4*z6+5766489465432691937774032602970086117601854272130564507021338128339726641804419310192855303151344994600552120951411200*z1*z9-10358187466010156005063257924431444558881908899341670267802145542369765918901281756229783435380365710565397482736763200*z3*z9+4628346915664606165715816905186307809324183852642989047212073078917782269045600119299241689274615738768368048033633600*z4*z9+121579409083181473715715313408805945759602070188157526400867647111981075715765930974569961096221890237059590489310878400*z1*z10+783731340434663174678271747763005819512708668932907237381763636988717300787541965141507022194940284522726874033546841150*z3*z10-967863764665113061051686037385964819732003573464611503559900993576572655370659883590658933908971445510830475561055283600*z4*z10+719809486889419645739373089532701463456850085560643208027218942443870159732957285448827329920895999480221367658791600*z1+4014502711123770652862961505629783392041872927890736185565727486944417963954921649620930477679401741200640832320410479*z3-4202445670043173447574967773216752324727184527340135268624539800036138075494098412571830487255533490984654385272082152*z4, 14940903804239915432737296974733891611988770304046728845631445700631809147507295267719814535186287938702731072386826923406965103696098727057957786998541265985150033679666858323755520*z1*z2*z3-1063733540061002893187700865978722231999079918532517583407251131772627026236607981381734684526982461903394879958362649465412091503190095380935862780863435876159563452158544725764157928186600*z5*z10^2-1989359570652680174117112976330779517307194438415125240439892876157954907598905781197096676733079641445656890528016125937447669526657948472306038536892299484726668578539120075430981625027350*z6*z10^2-5151248078311981743900018808469518955749985813731795896782194735168997245049603993207613700510418959947038942690625595047772726530165248779102876071690956400365757557671547059736357305815000*z9*z10^2-5541279627623572509630226831391390912534499775114139358530085356459766803588985676188088236440371477433531091832339016691862015382828542815640618019413895559258239317142408770832985940709671875*z10^3-621473388455929237750899414698373371797315987615199440277006665063454052098900139589919107655156899729894598273078824675573378657335000093859395731949637604241021212596187422007466544*z2^2-14940903804239915432737296974733891611988770304046728845631445700631809147507295267719814535186287938702731072386826923406965103696098727057957786998541265985150033679666858323755520*z1*z3+702428306342655559466214329296820645955338971997230509516605761936726288811982383209675177893280697337656102158013497517235707408832875921105111907590907559986980709073067021960853490*z4^2+2152402836849684318993274308975945961724484950559222250311826803856314462300161975597538708389037049553418340898334874545957495518378931521476129227234750286037989403983507995020913144*z2*z5+752153087884785122068713017407477727347889445522899526536273153983091358417179189857116603741212558681132013017428554473555765462866934860401629142984403212091957369026432645835734970*z5^2-2891442307784573534258437654708587107256714997682030024853859166812088573161806783888811036402176199874067814365817410786473414098622605670222722696757854540306321941789348572643505152*z2*z6-1185667704456502384704011365258157023435317345755849680828826962006771629959796344605020393339657011615520405588261854457352622426012367424368589196468705797561753554500448008855929632*z5*z6-983515883293168339343778314740497271358205522333452622439577507813413928051142599889068392120818047738464603678926355507341895755046819121054605104170856027479884935470517730405136498*z6^2-7278962634624650122659232768713828294685850827441186411130313088223787098695297560354110313257642557406826551980338827633185530450480691865570928914979646900837496228747174203760401664*z2*z9-6753289078997876502417716135251007428301753875301997023365828623674346013506249783381065742879968227207614465800140497495820299059883292484120203776120547794979681591089593134776961664*z5*z9-13699295083450219230218170111646142904244341841416369491103585668473570250411731937180597189507965281432867193979851798117244474131356442310502813847229539958461699584420240307358366336*z6*z9-221228275567763368991752041795743250173948761313629727451200985495550003409833047026399392051968996153601817166281745787605434923892732707480695400584303435522272827428545249280000*z9^2+42757750911010575520402324500724186884764812463971142426527357236149341957739614787077350283583076498975559077811989818883136850551498512806288566359239987619113924182330330458348026082464*z2*z10-6224485282294450551756906320591535867430593542576339854532523235601133660287062871351961518589966796201025518467336738764900565611328592826151434899135639800505972765469883789141604462212*z5*z10-30742118876268066010091139445902154027285971202543764526448303856795712420157014898154119641463016690577279072721266558796162508265985326956578195558779818458774410645937170658223740280968*z6*z10-68989679051411117474001092844586236859199323344636731757262416269117506185682430546637404517075218108563474159493267919214446518180075790477492098633678452530159807538436312985073814650800*z9*z10-56438959871735314582413014305585129204410618514611076753495403603906671757539645848926770475744825423869292464041624605059552203551106415871911758149021989062738971294496211851694283825168250*z10^2+191226868025399030379022866143743807802388275064540067548822885407985633418241096039503876018716993932595635087290517820842772970957745888506181621627549603034441314033551305420373158720*z2-8053552234277561154803510697829324005487268990586915938574210341024596276545109539426937229850666168051454703017825040183760779996001608829268954923713137220524553706320737406825751572*z5-95564831057678841129606748895366741424627889928754817624408504437765800583857266113283570245212790701124132582360816921537452196126971826867895861734872416161595137252111710033638759890*z6-214365669352899133013886037424458894026194448734478320572810993561735588266639719949063351615590991444155701755119186542563914932349196800133817954440229491546412370478586838175635725912*z9-94672061742957160851312826774242792993961442977607655678254867439881215310798250335857529409297151892159606837715978909052152746394221373498548419714393101914244837997722721258906281275415*z10+353300711153384824616956044118698295017926969853035933865926491443528975474273749571388527545624394047324718551316776188812361034952751487963778616355610911336354174271403348514234481202, 4*z2^3+8*z2^2+4*z2*z5-4*z2*z6-1*z5*z6+4*z2, 37766570454606102905199880405289418839960462118461777355313638028001597556069350248102323960479890192176920444331600*z1*z2^2+139406033309496022444594942825909539464376198254663578430683462487018780014932880354577458825688204879011682155110893250*z4*z5*z10-32776691922357094158130305854464734689435250696222332932115253790262348223451896940618205846304303627018321080884790400*z1*z6*z10-41838468926423264236545183767636758191482389127407569683378967693677282982832350854085889890105982989512754498597117000*z3*z6*z10+134291023217922925937220318184994309726297100212183570715862841019274573635671331988156524598691104588486611433288178700*z4*z6*z10+1328696405762697357709419608401335882762637454393392901720645385750831531691812368230722492428028181793851785195762720000*z1*z9*z10-2378913023522703019866090207235334962767982597874546584167922562012873018003332381512681019508742051135600334695234026400*z3*z9*z10+1058886862254062065248509535157590959575245628022694949743600011106530773720445443870499930659435859432606021968683780000*z4*z9*z10-11714069628158765941336980106080902024217164790322881812145984705226678563358977178038798762405804038212802934763743750000*z1*z10^2+62014768052298858577252573140981511396273000176492367669126215523212089958426801111853105379349391511484661594308697734375*z3*z10^2-98526482473393519796932085760887195222396359996003049810321992360428468631964095228674024474926055953374885659529338540000*z4*z10^2-259062940691949138583128690602843420914834432652468985125553625033861911840114236094480439704408838289401451703135600*z1*z2+1321268876078154088346653164714913911414855565833667168087898692635347197902388250900885297400812331557934691797162296*z2*z3-839889309793605898909858580062659589800966658754034393522697864173346311384351326324129897361783697244133763439335048*z2*z4+307720574994959871559452645683144174120567499977396746607337070010946356701405278379485404061108760132744535177801624*z1*z5+209630493144866937015688721300796481311553167678692081334823717884091099532514410974434254785144765331008538855214524*z3*z5+119699267685128202832460381886812123932909908694972182037494549754226392117526015624079338201345653924199368558877550*z4*z5+203962867138232363082112021945484367619497857163963857917669370723187496218108549977151870228444290035418627687369324*z1*z6-735258021333684695082122482040948735907173585735501256594960145339265367563768692914320463387889279455964644840757724*z3*z6+711491799449266889783825974678525178732730128933098524258842190295196419611173292056845685445840552458454930574206524*z4*z6+6041469686293116989537098025394444049158219400988801601085423924865149795304090141357861557424135881269915781811308800*z1*z9-10774821074252441339105020387993205069269399991498506641498394739658386213573630583002530664472379461376164672759856800*z3*z9+4772045426679521849195316697706764471054013087289702256068162391647174633375869432853571599417359031263223084692426400*z4*z9+110025229688185708677475681333334413437364378881606327533592598835128109728021619194325879051695162197186328144818831600*z1*z10+801180828227073849238412070280542007610266815584037448078535076122340703130272228676193867697708987297228477004507476350*z3*z10-1023012630258090308131358904159409563768360449226066340702950041328891435848178597649141977304563755120722136455439216400*z4*z10+764816034661852180926459769989872253895461195012529148356537451864440695226311018021279315853131651991728776163990000*z1+4040366329626941594037013007863393691863104293807244687632869631473926349870312983976204418738352235092690365797687271*z3-4352073356905118539181656425311043391096293659709014573617881137682136906686055757050693511070692011223501384257825648*z4, 46437031471389480135716847151596887243867986360296716719221760909211437634140563598993317063803621259530350836436586737933958858071083591402997405855269791494300073313920420605105342823045075313093017886197244854286220282568671875*z10^4+38776038940480705516168793315383105950500532169532437787179470934895037160756680566105435586295705467590391521208907568564634178179496868461169421006663212342714798104015581146043463249106148012037981725857823003331989964200*z5*z10^2+45085348843351963816688521424460231748142030235224989024942246066494368972964587473349722335846861131701749273656360743253337693880930955344707874981045926319867822296092870695893753027751606568813926594652993054443985701200*z6*z10^2-797881571343183588593720608011390401896319441593222578408688939917065120410304232707254154373689293053995355883653523613155428814854309558248089093977818378418190978152407464547973755824708580974754854480915332281882937720000*z9*z10^2+1364619125538958843700369030252247345944552910546940719092003559325448084192284774491782232415182733194251251625677583314619858291968206919478741934830184307029883077380967480791991356060918282033711769620520817084858353260793750*z10^3+8297679534880895147305653173423926934835309735358121169800873359538171549198719283784509909862641313045574222522561298180543364660341049073850514575540554254316465823268384986908924392099889323123335883699228470302848*z2^2+67571834051273723095514645680925469111138081883267271521733835898621331677387989103398528390568606652446384510037936175806664451625847150521871672715574071660359655611831931095568352970949530890848956449479782718771020*z4^2-56761309161766012443643309161891460490606361461911028365107180358181365598785752440043452159515716449719050327484136588145989089543997370260050226188534432361431899599556706061381895483117700194785751524114193528507808*z2*z5+66206651988283195826732750319227036912085628653249791349206800980689798433739498988630208113545181738487619987878060971597835967203316692989816369508805614466024340065280453521661050975840750870855378371336343730466700*z5^2+85814091965098340640754852190469291766108891515210906489044030987840581758464865268270134637528333207921889698458698388393106568620943978653702844678239573990267168497295610126450483521277761845212032631341174841176064*z2*z6+31105609356095636375151765283823153694319973945620156530819277395685806008206141727837873206887785632914441386114640410971935904628812601490379141407821969642568130140444814746907601828701340477285428891152025559295744*z5*z6-59359021800275998269137996984517630752730057875181615344648512101998668571286134846460751605846413603724008555496301319531157824658046684437414694098723291121180803131240892088129795132241320657049916516969088651377484*z6^2+173414497575964831368870838519785371420894829850495290619041180561275798001293951904307639649957355214053708709020263440144321983968114571519210214359804832619331861404268104487699250013944381570663543669469293698869248*z2*z9+142562898176580787570519820707664123409031006806604756332731055101235399256246241527062259151624807830507115306944008877159133086389668517135143288630220982112183844074054241086564789548140275298724886803282300036994048*z5*z9+292389732181219677158394765526095781295287688397503072431207569245219271526510119967673562832393895963126762234213671343660583750958646859604762142355883093396478606950678856654272663004614100150561203009329272551068672*z6*z9+4793831571394635072170304332609272113277661080831649596304145155609688059493525692233891385630986768601180540277584213244432566319163924424101071592544015028583791798327860745996188206189527049775442158669660160000*z9^2-1160188713339067995515138381255451864600283483874783330931191935900859301391052058880870774693898554890771346972854391922735625483157862033982396873484808972097203314379078694934423682053771715758164986786654509725235444288*z2*z10+222282444315921259704824255633674490763469215149603364945111026581611245883122616085778193536815600912768228396468578855973892324212404282596409820446005401325454894623687113969302070683076054465613339667256452034867389744*z5*z10+728854326917331483366734896919182052649387106951754880347694564865649302533881783461816954022272306734634336733233028357306170073901221779256038886306648533604088285014982872739314735141498219295400256244519505539388296256*z6*z10-6343600803318553687995472561367380434125693956510714686725079121083363308451176069596188014950528182303120969359103126778273113877565537737833120095200421789690245388239390482832835536157229492504439142291999309907227222400*z9*z10+14188209833218296962244347542432032687970862685399351865565387160817543904491650872226951651198529673195193644134486877509007649717386719921722744601141812649616612984296268761079090290425876332760763398049220592796289286136500*z10^2-5067366739360637552739176687856968739829606550869294076248860180282492849682599514748983920403662221715846719488802921580999821800264230102687749656155391966788671024474496925960789996100199096574281335337159080414699200*z2+269086468145954803010555332494053871246616113387646289334746827805945033040238226750269118236166224795752226966606048315363566106214473073005235212758306793136159645212793814896837095419456357036799412137758764177795464*z5+2281686180147647867531713289659307116250417865401374682081824345277683794833291172156189819047945602486213814525368892040980308610503344390455778890917220865119169657334728455659651793797341771044309248566214945106281360*z6-12226411334322265382302782385036295802759097697529477964710590912477029813414495376329990398388056276178659053542816504376754963101144368364193500934410345064459782778086420265639588611260323127994698164986402469243695296*z9+68133547024747592931051156432390652503715379667764261905832898328333417266074702684509328593059932144183537381177109577804425495127973882722964054089696373152453280675940807713345602369805624265342823289757858478623289928490*z10+139788716314922411102372584438996758411490167342044462559330340624056309269240115040984642633720673388847264974647951163006737338262011729430170186018657561336450142311710084647290549869031600258326146508781104394941802901, 5145966807087758959163608815211386130764931080672344413812148931192950379601053905990168055545423757208222133879325215379974614267400214647708483400437522214001564944724126069394067343750*z9*z10^3+65889516309459917517697054679577352023484491260658625948506462288742878981890565565777510751532624042290973627850870216786637144709965884951324006347564303439179187168774704653571600*z5*z10^2+132417066321132561707874334453489970227876044069903367548472484956869275575581515434966358381539092079057636148358332082807340513650953887149801049613606646667309836058447816765606350*z6*z10^2+66444979792834057908718940566381009051071667142859213433777140258566185626227542382613645271601735926479655296449969582132283482126959342905725225018453519615324298100265106695803515000*z9*z10^2+430416936946445897278916054097804156100020812938799484464606222186971951604194304000640405537695907687648681531076266709330566523778359986221285272601911868116156340702348743241415281250*z10^3+29453033018463358952489069448764276180263326081502050922333996401356704096648416775532138467988420710358606008192126042029954783488662392996840288409635127195030142341806486384*z2^2-55425168388060359757290889934418182962473979558720669910205785721504115683648029083518896694140221473693888098624211183874932854218833847909518668096133595382487437039164961550*z4^2-22070762957051438400332662095336285509613829368433360109262460791944433965579494803991947552975779333398285161031138262084897540792270730024791691102512649235050125749624204664*z2*z5-60262648989428050976339910958321251023346505588043765111942826747043393499631031150658189439019614267736726253463329188759797445766235408331252731838404124540808402576296924150*z5^2+48661066310803748386298155948190780063770991690516426770366140952168667303705538122875227069092585623547076727292933207820648438676310489086871167579404624163579615616407739392*z2*z6+21692435866713480629356235056474364472986706718306668200684418803175840092985224129978766366011659739892068438650890338136116817116899299497452574143644413471476332132074488992*z5*z6+73187214724423988172894613456956093612376621084013195479804525582033900905457323110377696796785606870957330279816634109853180958565154806775663344330743116851020618010520033678*z6^2+517539960168933214636152994156889717756602176102161907476865650106290952162196154566396676434076432485936727500227705339712267018879562695775797162811807412773176968206597884224*z2*z9+162002340933873007907351118549288404979328758846269279259192156921333839973990131689707364118289629556574305915074032740083950543782889739535786738305634646620349529042585203104*z5*z9+411713142978480985999359682073325684131498926613870933699612916142393231353460410148128324069988298498617308654361821198964730211869092513566579251188578614491167048936009887136*z6*z9+7695358591439484701683112577230986243178897294939119808256990149167822145241943126064387644369115035061542421307681051993293479799243027801366449774397913959020821319680000*z9^2-2490467986285156952482416954262316101702168020736038763261372873634179874497997255441492286850951326997005968440067463329630952444931569042571890013397706181698868701620647156124544*z2*z10+374622112300527348806410195767167955487352966949973046557993865955741879687937687117977249825122616683045085586923671796735104804342901890515616824846171200174871166887276350084372*z5*z10+1979268085061024947290208190147802159269006546837948824986359036071454430635323763132471749280658784053144434458140437564675953183439295211929084201732725178288757535582120863613928*z6*z10+291269081195326840605940122801996914478019290139162914845181633915588312094078075392310719083419651359134522711719533591465354082405296685984215432322507793503327442159969265791063550*z9*z10+4307515265225449002152153280813672368601195050735731336425851428919198961618358564724745103458987941998803988658352231075818537439589880709390968610760108683282780363016260215818691625*z10^2-10689905752135096550960486262478462762789751232493505704858673570865947865542966137563822800040877188490450913673326707262348531293628433243555302767972284417448305649212262003680*z2+419783405400105294713730943436417794526911474354235655755503671051810765656527785860850596940723303299383911982182249947999584009923831070679749847983176066211820074523639225452*z5+5988602638580862345504238600660340415487662584613664716526676785195251827042340481815604743663116942002595824260407854844566787281311074024055000890516818099043216360806669516330*z6+434153329041093112204415880925942432620325473792666016880638915094955974703919978993145660595668367059016283562180713010011969211034551140892700829441152641881984569721310897627052*z9+6521501054007045344908459640781883561530479485387707355358609270416302544748398344657357524548690429326339776360229678069751019390397329024938730244217673451679145016132306871091820*z10-30008913130756889268388599869956022871486415538347094587338660580881983310250332080018049902250060624265989504864539809952107020904648839870595476151120328835582242235508179477297, 45741927174113412970343189468545654495688276272643061456107990499492892263120479164357049382625988952961974523371779692266441015710224130201853185781666864124458355064214453950169487500*z6*z10^3-391754821252188456410784965667895211427104164049164102416486709103474845247139684870756544960066630959430074865629557719925110099113108401274842996450770531778036368660415654417133600*z5*z10^2+102703618213568323740140820058590366866815354693202804701769173845756419238436525022614282957050411869670770968121961470439852430369335165099053610725703103673585502386835448007681400*z6*z10^2+10454753937408278831254732704281108032322704007116526073752927344166918104025337493448760585644259271997702188194921355456633741162727155204019435626440557388446595066577821682351485000*z9*z10^2-4626276327659264989150334540552879827073755924827747596805539600165290810118554447135774746231524678249585107958440378473134667834980785340433428456846593454772738767290568894137535887500*z10^3-120837206289988000698384855760353430641074528029252170514629053148580583766783268909249225713705806768421099671767717482031678163609535399171145140331537790648460512122879955184*z2^2-268468010074395910305614694276093636875690736211520614025966289748473139961484671940967431158007719647501538161695875986923371800405429008953564307328535756713694189853181177350*z4^2+577743177324419694511723188428486307474904332458068217142618014886567745799709450021332489381431536712811914014623197169381574340258216368162440713106803063673986160877161061824*z2*z5-248043704124967554276801740726066021637293679078346506713354322288725871403746723106299209517355009355156503097825080459516629666580999219210188731213192403592433699475467162030*z5^2-872655593011465385451538547200849118581566536383720020107247256742735880033080366000667426457117831241722621215027222609351575661481095031097163961330088530760144236255801126912*z2*z6-331973527167552038273145383723661195145933314931398088644248395724486193291340987067083091518108055667774204596309316643308921821918868368839371209780402650227566994658680386112*z5*z6+156308687713182200833262690441826632154610602885747090675497391592965823566550203938704464336024806832809618368464093972049119012583036909477254329778797890051494916452842829062*z6^2-1997014081040702517363780087662746054740759818675159301412368006206506671247891978976277851276649909608252756203790252486814340701073615281423964548828871571396466755250865016064*z2*z9-1683697089824131813058556243825991793526150765177172957385874519279253261649851644120551811365626462288340445818379534697870164417697250670203206237436258555730039461259039556224*z5*z9-3443364842033021376381281002677180342797222435911948786826372517213539510273905173594223360873444868952121102161623881693979420024706391857357667691041144340484006238050395591296*z6*z9-56268549807915506318093610935250206871252293621026256175403398447379455259941236672819338790886448387691363050995461285661627896032240843196594610492213868098988194938880000*z9^2+15516453718173173435680501023271784203483228073435417012731125059656856532792405115660379324458760485085431757021166832145063437421594902192498994364459080176717658790130233290464384*z2*z10-1982210757405064362050994197125996366475818875802958032285948122780091271293812751439687166905310043340651257432998153333827367570167436421520129897347975741835657224804822434318092*z5*z10-6380872975675583988968303845330038583091661071854468707547843386051791036066180014231307859007237202476377685851255458482871742002097529532648429977587311020935894440459073343307008*z6*z10+84888134953109319316207611049386741188845290772087798914870029541838914097804051491629081224690320559536821549472980400865847811769984655049892485114197134269508480419426473117293200*z9*z10-67048011033086772809642634563835436933089064350761145963986608375318667132904253894030908467377589912537148351797473713119555168985199125507471783876416859388086471412744539274840078125*z10^2+68159540921583806890157713493912234043648744382787170033131693360925064315668304256806296358298766145028122320214628741389620561885280254156578618045412317213589222150253098886560*z2-1602372532377017662947740875873109418152276345525307283649358732507399878579315568264909442838114719026036107330944631825736956800021191051672055806594475309739155651501429815252*z5-25679575371760598472217231071224385195501022615013102800515142621048656541845712608078535092945386767745068515051922622309086481488872614683592138258014864696136281070160748898340*z6+168343020784297046955510007308577410773363026387261593344564017117416200437360709034355117477592607154277883533071016325464326591999239460034463942832159343512557571117912743158728*z9-345487470171861792547047118277473572880043858689173754254530855861186086129057773537194110402865844549230985356551139695555200272053123692068437656183398206760382830262770512540051970*z10-681585090605741115296016656031156880124403417571064312379165577305218602406574713709913430603676401348599332626710758599099197685017642777447161008400958711355199653873819799736423, 437721791139841272443475497306656980819983505001369009149358760760697533618377791046478941460535779454181574386332820021688430772346642394276107040972888651908692392958989989953775000*z5*z10^3+8748512548690140549163306848753891966140938943346445935690505256997865418098534113614717322111512001853809851481561896335765669118672295779258771007953470242814276882302006600972600*z5*z10^2+3184026059417743588056036037016448319490315860638490624538358197493952595542572504783194600974889048210937748265336732761861675828069203229457087729927026723668243006970468023326850*z6*z10^2-4165110978048893458384688402392906422250440094378392848824893477561983722796558208333190180826757177245720212416596842951852118228602404986774978665430956690064780877037072908585000*z9*z10^2+19750540929994817358692978205581292842176948183124700387703180777067477762749182695755191278323463124844592920437910647420853032457995398549029404258898122915935172966429712907360615625*z10^3+1510290323816046958098228115491108069564062934802455735717624176264028032325633617269369133090233120728941671238835749274441944820906142915632556648216669273738273171243491984*z2^2+917146683954727390114945269471328151739709516249745017448367845574757127835719747601838540538686574856103242913209032175983031484244544855554275305844419667380695867441872650*z4^2-5196342087774940733202424070559576341054890845891740327018278491109370622745903106036367635106254254475411215305099595025221420619713420521845915644103095658566655307914910184*z2*z5+818380296611299192748292358344980059669405092870573940777455976762574584964942974342532889069404955622809530596958058910819752934846824666725093080646933200073846248041985330*z5^2+6668203408507328172461604005384265452027190026591636442681910991729879174517504004818244167180544971707124358870654524191918835126229952444798384809965411317663955312781939712*z2*z6+2684467691471947033232779669581669830281193353148603228831101702992365754570516331475117420522799409978464602754470900639710608247248958842320330082044234527649775069794009952*z5*z6-565073577666735817413714453920117357141992343270434700592708162883521039765734222837956753849777973375219821253312158572052628342169680880712852583398449476764708896621555082*z6^2+13163540297498518553971532911685339908210923864229221206174818937255246795298158981563788037331902452225889877192064754312231536206749762770758877981689286192033835496342002944*z2*z9+11892164805895702502451662676561506536048916060177932771721290111802994226850865744473984738363193023119986640679379521813669732102172595822538002135735525319012721614746241664*z5*z9+24186462017579685680817308266941204504594373898486294814216968928490328752710246610511521388048812387088316561698922114317782278505922118462287897620003000921790663098579532416*z6*z9+391803767437378915132820681352128141742217155874490202478105610391682300080896845379224522968493488035009407424878542794434678432730959024363169383321898234385900257280000*z9^2-60610233152497380939337368950690985806672762626970634213428539301106131770108562091646509322393946193316745277770589351260961391128671736078255702461046196403095688385776124379264*z2*z10+45767722100194123127866906154445557402587484005605444913671128483707333288702518273397949818757104598994484472607774367285651459610403149925764415747145357881366439614566602934132*z5*z10+45951657515863479138639462746920519366874568440384955490078489295613746984833763226496498757826968076292632586194399909400990546382084423580941615837603040501709865569132457340568*z6*z10+8487984060375670422867292395879113826027996425455082646968876460680569806968012433906297473404284588376928266303616478658335479560040781461952950757498735192378877904194140730800*z9*z10+282915158042083523085200101013457121224304093564901675918283974312372675248107254251530329243315654497498486750993211265515891008901219816912452515666540512597317699525132705612566750*z10^2-263465476381794335640947169183264193122500237267278322631569701875115604817001212989929251037274551503544356236550377768651411455512781635656779353799208517559352332941493748320*z2+71885095623669882589868769685163730017999606849097469673745810260069686957895578085532985879346390782500195869402514431137838821883974411682362641875219814254673866107173871292*z5+137411144005156495183628477744130022856689686572994962639289240004805905155639993482856502117647750779669369376240584459610154885323471742635512684367397676597961243359324160950*z6+136835192075080618269186929055003355856507013367326632498189699150187728755782098757885732595339147668535445766392319280093825795795459068363324859956987459560426357060282420312*z9+1426502474397563728560270714834964448553270547320877944562185786235023530117218442553226829269397589776087538691778728148644477227348847700497910870337325301601429328082687770364645*z10+2710221961533363693264327879687932273309375012820531436822909679517608793465547390931937562590931868475116996383900017217082981124007586911695300063504082362096635716869601390138, 38664411656898027679735218187112041508163584667106146015409102094557916785468717691891194052759111331667501451457389521875*z4*z10^3-212386713654940133768005032137734882083274128350488127403134857619029395537186494149547879191029033036678847833867825*z4*z5*z10+206017385338503697220831556871247034516853312671335680361722358036385410216798824549160534941495316347499515886433120*z1*z6*z10+232819027770259373882641688545628066232259345894750049835136838250899161405429711588675705663686817896398889774285000*z3*z6*z10-302928680344401518614250475297623666088576708802325562267818412782227120977279193755075842291752745289001839503238870*z4*z6*z10-3506289631396200227740268135529192400509232952245916590394917716650868136579113511585325227016876497762250090891808000*z1*z9*z10+6874104116364425439876367375692865632824394781606677431645642092457523922120283034101100621116623736199557861508292320*z3*z9*z10-3408074272933057162556116720202046252013090426542955068800195534920263455512710734774890068834933004720186721482380000*z4*z9*z10+277420784843639561471491917474240280095870276700601602230365972072856775023169827802152614842771398882366984595918078125*z1*z10^2-360254913981173053506509770777216005186830568490141720045921507692431921145807416533333091193689314383977498885398350000*z3*z10^2+1184759294881925227193461832650607210565875856708091483408001903074303363115167778345626989599810456342583140989529077500*z4*z10^2+587761536196062694738390424348808598006064408407031088028959031447693961134530346836906263076357329595887514459720*z1*z2-677609055911423331248543631291902752717599862229150455943665591917679457256740042557688379471511540728108762297788*z2*z3-247749693690869940073385102745277218152834625637250947582919798485369531991506891983629604251893284746556797904716*z2*z4-255977979638301765639095007891229019102510449614088680199740727037810483648905686378274004910977478114881391508772*z1*z5-58541231242967240370213660392188143504531615944991134667098245580498085339230331269255518934041676303488004257142*z3*z5-602756489360129576520001397840073096148869314207466791890711298045490658729860678560743837303688352774024376519095*z4*z5+888410537801705576585162332180136055119803376151990501596430312104207981498940350291608817775441459526832496386698*z1*z6+1890248761129484729796473295975464466418681822806019243106368234695779080715799931090966373113912759982608144602422*z3*z6-2074163669762904841478728398224957037986071122978562134852842908785633157756623512404605298305244369231513238776502*z4*z6-16175508741809622861334173797458834990875186531597316525734492199820817314519224859799292209631426888267859478278400*z1*z9+31439209713061375527706205955954758178573004346216609620729466543560319917379242310989116510824906238293449382262240*z3*z9-15443377122102008877680751956368257520598331655448740569604830809528563457600815529050357624384766344827912297969120*z4*z9+1422749888627185465518390724926573159975162149360190622590014628989172656358119687792853832147876388009790057737245770*z1*z10-1146579550768028384019637171271924060875287043450838109243343556760692559408827047397923750353261079287511769107918980*z3*z10+6278475855615426980791194055532617694057574653202780935134276846814953808501404819244878349471870970546414274577276055*z4*z10-276853007717607921570519257305264686910180449694019497745287183936641736989802457628106717396694785775348513185875*z1-460281097061199174685907749243336399466115126247715797763949945805443295577421841279273956851259665770308287763848*z3+11687964603961059152908175673179972380687655320231097515564222015060683179194275195078801844007995650076535188998034*z4, 51594544771619627095060086424488988414372460310216045361523776639256523608265829065934296664159197557904841694449585747694089969178160091791852793988823558515625*z3*z10^3-187801724269285668875303080875721320824682495832256338955245770449634662876662727232930718681119145968784903915352709487071832513853368674802957703571934800*z4*z5*z10+121863272682150642791370894891167245044448099609606895142092886692122019448957259014013087428498600922421289515126350291850748400576813254076805892001382400*z1*z6*z10+137067887387412391763323124974176055172856505440291419437614188450483155330924065669504951705935255321912776030856703742359904505161995084146441922570651600*z3*z6*z10-231358115729106770248528414784963216783140338452339649689050771061620500941064755788608112867810289621240352260982728553345196921819579304130839918263209600*z4*z6*z10-2095585126280398768949286634664135210120364447314694990620871934259713332106693904477675187762564722349138292306721106619587463907249571317486342221683360000*z1*z9*z10+4753879745935096880792317744333240189012469116572937987138520695291403045933116536876154931283639321499647047150223321977788516371659254302463182754846672800*z3*z9*z10-2687577323921971832512720986808190638840676551581417263267438719761264093284157478595666806365260360668080581772110693775290794799558117565097339011060900000*z4*z9*z10+137159405612081220313295122716036888326800837761926954742222412947435107230037759076541103270670468168116963723931462246743012980047934135123232657420189437500*z1*z10^2+735493231501165050338445322315638527502867707337514405840024672922937943913991242498079205400542888708588656223390405872795694625851967595196946192992298418750*z3*z10^2+196659780909782501670066405043559703997016600087329169181517226034755002026420840558105570648257348136399119699780836763496097033537069055561320051066196632500*z4*z10^2+482464665032883034312620171323719597059887538891701832322084723017287852687411609390010008058109140453894414822581300643554772123342377537088298248480000*z1*z2-1088808715277283917423992765667816825437301798298605651096929159590460661830366980516128947729398825527271079402220043891862386147789955834881916071567488*z2*z3+391257098808074108075358357053077200869461817332976455379797285541276545453455858099511510885401526440791976011403172648561408901521379289135180429535744*z2*z4-286051374379978887992342887022896262672050726713404568794691553050963011294006570571653235171420904893172153543268631493664657882634755511263794629446672*z1*z5-154319530847951977099014204872074523097125796757011003097295869413956324794890980937478660925262187552883706992365905971116111149910266516963817885817072*z3*z5-377066989911165618526756187576305531631922595407155126320207240374630630104942671049539625363722496443538359951063500647846766121166788219614579256957200*z4*z5+320126900630843718358302711739338979649964609504845129352752853720814051901467026261738958544307305578978904422627837226289056852522574119196149053337728*z1*z6+1334255655653895093913898379781721356960462954514667023926277451865307386645368412079653685671166756641878124376109530889631187767755176711361848466059072*z3*z6-1467954757714540037456323082465366313823462598613214463189648310628492161175391654323262720852919891134947243970924676547298688740371764232599603078207872*z4*z6-9736788651236164903262459712260131444783617056409899224794451916946305395031317181378045450462062297171497963543107656581155973916411767063968128775865600*z1*z9+21766466225759229719021618055157206689681007544460687582854272505558513230744760761298686412133677162882207724016408253955117845566668314827794888028727200*z3*z9-12160362506704460763106318447792090656052562757201492380413357370040351053415931212436990283321441463231994059703585209892450957473068208316991076025072800*z4*z9+600767555430705575226698207689150465427914492599310246893134294650814125436727120038902757901249462657866709549715305195477349726137952199667503664652055400*z1*z10+4829882234879504722708536967022679857570283912687961271550812699309037898190801213679869300004230872031538256284112795930767792998520258976644578920097867025*z3*z10+361891019096016870029209221155108412337775927695035408657338533174999110359496554264276164942317094319227737646119800586894053130153714832913853429622500600*z4*z10-598993284123330729203766102407273096866471196213988550444026749673027545555355365715664023454316757508126334289451653996044607130761059674307364230231700*z1+9255882299043535155596312898312863707720146832918540964647072670121007664917630905556592191831192125116989108678553246655954028634665928973699019676044012*z3+626510716458273054845608280868611993004098338258693559574742612434336008453019622476078211642935537263820641956809149023251616559467338540654187584318244*z4, 2253701310169116931139319635108103502928203438810547077436720087379364207732659679429076012587137908526841390055252355045025543943671210969559921894225801859521015625*z1*z10^3-7817882365742796428141768028536015889123667207959735001849087072821424485936586695423121910350948145426415788545051808271302117734204174810291436808144596659950*z4*z5*z10+14002278965198751669577427884507203303599158456061949666063490176052726971160875056613758221606832527658155063398408600075087840308663302006110159759556408389600*z1*z6*z10+15720821752022547416523887262206861358390064528583705600523927326940130834319568387617007209287596446405266210148858439327167022724650750353159593689922224054000*z3*z6*z10-15788393301174233334145438328580451035773195031982660399152044354361086567127800709279949325549578293076524667848939780988728624811107068044073171369549782511700*z4*z6*z10-205143755485899578839676250194520551816004578655857090828564807748130917677117055432920018326234667295249009433098920637214095154570559451367992191050804859520000*z1*z9*z10+376370387077940602348360753586036609612872971956661416793654810044688748007142063861454001271474569868604472015176918729541474926673811587674499081609233857681600*z3*z9*z10-173344409298149263861604947963244680494898250319960410891022850129999726242959367824607382349901733785695666513124308423015340956926313890978343561085137105400000*z4*z9*z10+53717881300322055750874232198973546052715473072523663849445094526228375126482453223376421941332581116684330150655177724920733659950772187248344121218396571069340625*z1*z10^2-42312613676054313508483006436185479508150643553114559517740043228427332965152519909902504074780322746925278405871120822267376189211484833072588954868293201675171875*z3*z10^2+46314344101573513380649196795847056797883364429988500744908896518557882697270992110727000520497668009709155131653417446751120906488187500524982043123723336020361250*z4*z10^2+21027756864058977190636061728002758225694248859397133130753604052210538005091543038052185476770676860825184848757948120590729014221515147863833073941466199600*z1*z2+20898161426969297923853464888137690686242349099688942285245213594880884797314159388161609058365184662812298874102287546130371255998473244340395201442725884568*z2*z3-59978021951820814273766133604637755974429425487256899380660131952189956015741575803852663018540989293157898755047747655330906954593764719542796368985741316584*z2*z4-4375763889442856493537873939400546006264148160401271948234111148287295540101117738919186850838398611810588167142949119517254483615470660391850231772685481608*z1*z5+5496917488025808949409336677942021157829551481826278946079158738754809064517964373259109221173639611348457307458658882017936378790974836967926655030980867292*z3*z5-34515502087713872136899295375015117480503529573526328754975469758135606038908215404582694878456818279867972982499256072880582030905506620916671910931828406850*z4*z5+82088072859466482471788267576060142816572973218921259103437629562047726183425545785800161263640758506158883483352773056468242738517048056551404364428032463692*z1*z6+104200153063219241095887587632771779905750059960842948618595884460283539802644297422439339159842222148729609510615295318524401079654684827283309273670512550308*z3*z6-118888956050677682376353678681427224504289844189601380635757616420056613791993422076467836334200611236595832387322585873714546986070348050534330182486821857908*z4*z6-943278018749500491991638342498817362926528868733287196526328383133659962838757105727714957735639583997155302815242479175044210893398419719966675165029615385600*z1*z9+1719700784020295752646808976380995632085273054735719988204716591913683621699325551925827174500552482486415005504350236688737664029502614533242674612611383876800*z3*z9-785874213387954842429968139611267861141546838080124338678162121084715228050525595898759685225466914211589569913074015293652329649849926440470681251242590993600*z4*z9+278517050035733708211742898394537630414535456769886959442991707379360045536638725184368130143653544093262379634720395668654855138592649664784112582032450714717975*z1*z10-284402348868114569188301769881280966999549906716501728570519168264252769732022288756612239708624274180768844061155349071221371085373217698765679193896899970412150*z3*z10+333996547729237049984572926452491054936488725859079018295001110583519452417361801549114350830775079133548763344668429873983273746749030180401861949918496760693500*z4*z10+290482716735827473809716759860009198725019339622996991798839864611493470225031807356155557107649674841995745577678086278145358863397252021214403390053644900975*z1-515367712903356614404674754032391129224935989232916637788817751759709560789023481676149727254524122564881125249232603306389177366254935500984161925356227328907*z3+750709464048628324703240615051609639098659638559621944590264099448717181203076074015232316186664402072972703285485865023697357601522592004290684785726373588066*z4, 1593277191053694966313119954598147357310831995622606232177294104306317396896675713591816792082745367482463831245239375*z4*z9*z10^2+491539315344817322148693541854792358268224206639032426486201160242670305687079562909315651074541480932107715811290*z4*z5*z10-75807823402462961128648733708792651964258997477628680456103577607968830132541133340716429504965963112373642414448*z1*z6*z10-95263618677788356102392921292664256354511602759301904195411684808630590185659500273990506769616638084699268027360*z3*z6*z10+412616560303890461609666764746430644342837231551863173594955261275517029734408693228045782166992375194018226562478*z4*z6*z10+1614242809922551492571697188658171372913338908419591965133294152509259955952577740390416134187107436147304421484800*z1*z9*z10+1941733331954348224604817007435372771480077435117644862968651740963261530035383505305918399265988623986721722952127*z3*z9*z10+10637607028459399106322704296287948487505507918534443191734902978586333513127036123250432326099798367629418659207375*z4*z9*z10+66135521779356371323883299104412097394623569302607461563432671851229478890065020852559674845703811043152892790784375*z1*z10^2-119607664208892691270796724728944530652110186283382558152006337283199293728288270645008952104892062477234422382584375*z3*z10^2-335072924307116162641163997620350741063373308656394772672246008557618624900221342332343309227663509136035382441686900*z4*z10^2-1249960375989034893169814857608624049026312092090847227094650230837556057174911507631429403760663353726684717708*z1*z2+4570701904472509796104144633673444916056268355355704788798485009529196113472159266065255105593773279985683172180*z2*z3-3117786810455007257052447116065186903149421358451010304147898914696073139747859997694081603031005535952137439176*z2*z4+964209178424226846596072198591350269189179065875715632132315296963249102847128859481078684936351753794288848800*z1*z5+831809318711241434498911133861409926100802665884118690309266508850106383032049785676356560748963633584298838996*z3*z5+374081052919548709039754814263468702575154510807664273458639274632333887877416665099347516759893261391165191302*z4*z5+1013143518382338171081451957836434838941206202700087017805297096269738075706216553563950817197821121371109745502*z1*z6-2138054035557448562975560186924123083790548804423099967999494260659299305469040623259416803225391576543435864238*z3*z6+2136050052337266501222481849102309654712455028518054237946622040442959826966016774962717483095030939648882498654*z4*z6+6941486190372363012802288871233988639300259432962336882599569971370888890992238407843419173382363316074594855360*z1*z9+8915965352963769194055724633756882391423328102735851153260998159650277973518206790028742313304360237037361217119*z3*z9+15753095917962712881659220346610086927309739367229578601655160776975476281291699586589439266372715197224895815968*z4*z9+991992773935401280123733112276636073282995843265472211320202278085743880133334160826686058368369720925615698585342*z1*z10-2380170236087336176674631246014189579063775296129845226184161441543348227427127496382760922761956152760675869351838*z3*z10-1140544597336284256829220627989231324867039967068012155488571317032964143736464365023493280604886699874670289456692*z4*z10+2894456584168235411096398451995074544708623279876792408644040853286490798832593619085416132768436350762375755735*z1-2512678391505420796943128551661346582962149888218314933339264950731588521831415977556825416826782518710137109687*z3-4102295879193197729661977372318758058676135671868834532006422302686852305304947692335656263919460035177667712288*z4, 708123196023864429472497757599176603249258664721158325412130713025029954176300317151918574258997941103317258331217500*z3*z9*z10^2+182499822944967511865420101596266095514407406564647259234610933713945807037590111473004744412105855948001846382625*z4*z5*z10-48414780206913161080941115851202529314953151106442233653024429324344634187704855245577179410656840882644072840000*z1*z6*z10-54306088275873442643989108705453904004635244281467856134143473445494255179003217685183542751991584283090365846300*z3*z6*z10+181140301844579410406699960060216288921301496978771554374714674630471087140046479292897675981049782838004931386750*z4*z6*z10+720385605275906475636351586030513485808806646831639986387984018940669312897379672854118306249519502410529752880000*z1*z9*z10+8738734210605586191867646647004914055719772211212344870879282599719676202817692651428011404251430707601812676180900*z3*z9*z10-3164122902007760574165254202327683096754028866425548506631397827078929699886295386745521028529599520716174536627500*z4*z9*z10-50267454655004662112599099156478123793889210086468986079877072814690559203636318178382564079881047983754084083390625*z1*z10^2+41515905787422815400849352292859164052385797532170502532379941484395638406742919540023592540439835105958188324236250*z3*z10^2-68365324802193630690481667908972129076258233815286629650043449648909922841531541540262290948934526942579325566895625*z4*z10^2-409839624667687700184427046143087841135212040843256498133760629048654832831099171032835317667165833422164451600*z1*z2+1762597127799191214080565457075109120790203950566803075449799785924533442648072229714620513741058899402821817756*z2*z3-1298866645844847142634889980243898206708057059541026749266081250464567800858656459527461721557255396008766294028*z2*z4+391239649882744738033712690745722043599116209248362867493590658358462110964514860616186684445687893600257418414*z1*z5+358294615405365092104916195212306517513805272491292799715781244786611296355777472819737945416825434377981214664*z3*z5+58307791229744528289313520579409741011735305929443713755838985486401363076009434667432593742249364805569907275*z4*z5+243064891727052830945286498628896740717238967358195469281591594444332328969173773258854639105899557468758692414*z1*z6-896394475968350038908888377560121434432054297552014343448382989705752646545354468732866900668023017691032398014*z3*z6+984413804551311190205783511629097969756404035451073715015914444845440463410797871186413742978460150855132241214*z4*z6+2922500773972299970659550725032678602089249907230978849961218334074744627480435747537373087025387177727526377600*z1*z9+25252337466567032393871614157063347531361195535964748363659571383873864918989672790882317864362006269835009846600*z3*z9-14184891778409526741987525976888418373949784086149223399065588551999110619389937850653181408673965865577101113900*z4*z9-208138597998200197505399999414755001378374403138088998059782817649412379669861622161042791149053649646579679826250*z1*z10+206251238459484188348718458801823097352528070277944877582872319349675732140124770826939886620945728777863915680100*z3*z10-329751996748331705849147896182376056155095132328110882311775686579838888376544722228629314665925879567701147589450*z4*z10+116243235195788678243979483856816126773592374039270326948520743191106867310451824786756726218334149097244393575*z1+2290414599705837772761715179137761151929515438280387603493759032716397876741992911341581676674921993177407721406*z3-2378043438398017125377433538331840725127523668665357991857539283594038480840783742294783899845009713582573844453*z4, 21243695880715932884174932727975298097477759941634749762363921390750898625289009514557557227769938233099517749936525000*z1*z9*z10^2+10288449149682941245247223646210146343180067330610998743433092396321892866381315834312272758193286516101299157675675*z4*z5*z10-2202002396523519973573002760951641224552837866675203705945641254700191972020064741024200445341669419936163644812320*z1*z6*z10-2507277170036822849626011517764994916408231968113321993815979112116040095684012410166871832888561080628047883717700*z3*z6*z10+9387630250560525785555536247080787849765746444598476143304616394436906107546071236552421768887476682684486783347870*z4*z6*z10+224928085020652086350997346273192621725170248894079819775097251994969826852666829033505397610892725917634277640490000*z1*z9*z10+20110395346393494419967546314572011833929734867458329084125403951326280054569155111481048847907772703940553518545080*z3*z9*z10-55803099597521222799539430311326833230101689352074637403221431340104948185065367489581886006672523537303602838675000*z4*z9*z10-628392887146951374351804295255177897174763141427115574511455828258857419629492320768407941013746024382247513847240625*z1*z10^2-742736480334672763351251407096717784980167618255211024817165293289238497907787387867119434160703503483311221907562500*z3*z10^2-5745482173012612564940936286216992358765826103701217264405465617051777559618187473829817041879439243566928465591917375*z4*z10^2-24591955009865704817744896694032632233802996717070462684159095140217183250408003365331730750965522451527430533320*z1*z2+96657961811795473432135357100184156312205553837675521012626755609409565413593186106057852479262078755036429103628*z2*z3-68035300663991995127577564675932370706961612392028064360445899839932648235450550045497800312629486200821639787204*z2*z4+20985310411126464138302157282990259312194718569425144499057055499909211615207013808286057772345907394495525443722*z1*z5+18435972535887204283838246890746551878130321696044926367904115273726427958171315662279598297256899103834849793672*z3*z5+6019102440529925716538764397333468823503726705361253487344866043951706467006853975579195405145866172609812529705*z4*z5+16997408092533960908913461866716072390131062615210522711327469417413810685156267097060621156416785223614155424702*z1*z6-47548230798739894398146682869607151792796201983648865961361641981274696051055854403970241439482262700161068089502*z3*z6+50092880726716435214803260421146270553713249937192830605727461950215072333489213290817696683879909720345350129342*z4*z6+577014942825878237410919830996081423363976775867051621519143346919634600821873081382457730593973364753397607734600*z1*z9+93204486186994687610127869096827974868720823082919977275187046472314934972156818986014287999835299057729702971960*z3*z9-248800723548683742634187452228174849664062154974533234435587182500954583693565368032679893782668419829608355940280*z4*z9+5478247080403082583560566601404356838104508575653804140533246244657150211171443197106397863164209370032642503173030*z1*z10-29374856762320461082902556404161516346558441237453426876904027617890156965072595325010800405970985551430366449820820*z3*z10-19660204667847959380360596458822016776402536736367327520344828601885842641217048788867492933158478939886538366213830*z4*z10+35009467542236474301547290800028615011660275611918720631715532566960083839680228654090455546941079256149461024375*z1+4302705369007792234468278419402106497640334353141807378377034051124443136632939306886194176124895888500454116748*z3-94616889796863072089770620169371119870133913001814955138453696966158574038844106878104145092933224638119758543459*z4, 2832492784095457717889991030396706412997034658884633301648522852100119816705201268607674297035991764413269033324870000*z4*z6*z10^2+193491310299764535971155861953751736281702283092295295453155196960793870929094762095306951481440712387916264613767625*z4*z5*z10-77489701520303156305950937832134574929970954775484366414817397008814076839876885207045628821616938323373804253250400*z1*z6*z10-99282569855061169552502459251012304712143604087184405688518690607756329989374082998189976254391405236952527013825600*z3*z6*z10+226706310304469067058573834545190982414923941992825896499805898203623876218252740827252069466778129348498504373082150*z4*z6*z10+1348796211984804438949224623619601697532350001502236326253829841233688310797065011013130018541205636935739654213440000*z1*z9*z10-3310858569154294849685100768724620193941868513280594783053599464413841345276327349144897404630213316674498097232233600*z3*z9*z10+1983451597160824322872979619637671494111857773890096750107793878680049879396662459836671770380540256890528247649680000*z4*z9*z10-52919945959086248289756146454024689236306967626829839695826366448012173492447625234604464042792400427122271972712578125*z1*z10^2+86943729398974931236305843756333847178605126598254441502913659573410939892139138134533512846126617652041393553500156250*z3*z10^2-347675723745134947209716685484090981574225636276790229008582916085064129246425285756912012904356206597670465782331713125*z4*z10^2-470815950205726134376349736891663144721329698860893968653576829000153770047483357523347706323685751700584559486600*z1*z2+1411721086191218857456135734723039855482599060702048255110502399850531828214961904001331873549635769800146769343772*z2*z3-775392837479825820340649471557935480446040681469323123663691401331839819283195195712185311976694704658846177321236*z2*z4+331321568933769319814835703953889404578245708931951371161977551931683719796595980209697100911905551790625347846068*z1*z5+231104987839482256990838787104685370134687695013883361166874828596937976347083910374337282052342205882082526381318*z3*z5+284651398810700683035029750459123106469497996954319114236061228319889947329899006728144358495127081531115537837775*z4*z5+8147148318328389166428479457132731540199066075582520035874292881218079940859288752313505181355118951582997438918*z1*z6-1150811425351755996383831491860004003888660470476784745632129528370458934145257727992426108233350376008122173748118*z3*z6+1258448497213890981258819082285664397163305908634352197211355156234719257063772358011342135808283740630979758285318*z4*z6+6300518781434656775142097781046957154797002568740175638784116455331965084338788441423202680693674839988972563571200*z1*z9-15178999487261454671557904271668710075647661574497131049049409207090230017643133761571188624800102796523610434153600*z3*z9+8973938572748671872988194080271951736043017511103034447220453971622012553994092909881257132847144193353613379113600*z4*z9-76140950306059304361924344842122720729295129153771339023878193092190826481877009179980983379528231527996805467214650*z1*z10-267679722998231194444136810350853031878623071627049893893349883736563785026917201175027405823769936459123767058484700*z3*z10-1891352269143817996273389827251413504496201475043384566050300701708298020283011790811691296713903631151844495734879750*z4*z10+1031938354027916175703310379814014308462322176407753376720724066615879809284185469849764972519334655460428978710275*z1-625544000849857958827690045640582147538743523417268983757527933759266264377534447139903730093291233888020803870778*z3-4241570302158674820214008883874661150374242235556221804463631801869154211076436531569910860705274103635282052322061*z4, 524535700758418095905553894517908594999450862756413574379356083722244410500963197890310055006665141558012783949050*z3*z6*z10^2+14906729965506756680883975739658989953796117633870270390473013112186678626403242170973389496616880855758607644100*z4*z5*z10-2018895866457209271987403511437259999940899452776565050565991752622075592315395377491666172911041865964453897200*z1*z6*z10+2056297724766927066147752797783231250076498545139804716141735555606592824175958725095758646637922460540072006850*z3*z6*z10+11830048462419614187538828836477247796335095560206625315088656550915180260113113714251907671119169636449484821800*z4*z6*z10+33088276153853276077679958320023460395313907762097161529484056846677614765882134047222498648010071783259405440000*z1*z9*z10-183231867355060063670198749754634611347919294164945413123248391840912099721156470185822650980013939296442509302400*z3*z9*z10+151602834776180905030150033544526755881570100903340054919047574059073623482512261158339819029504731498236332400000*z4*z9*z10+4011795460482730870797867534823279516378759784279583258715931222380510978526069940630721711262537944075823325406875*z1*z10^2-14833275724766671200648532218144277751364563239189053021619038788480401853919102828672757171379434192466158626756825*z3*z10^2-10359810369300333213974797877738261042788091344069631384902881151990825414851748029826949055734810650073315493030000*z4*z10^2-40799296974282677296309714847607279891197450909648724405488760267573294316356927591319198900313732158930052400*z1*z2+133204431018492304106400080528644241523276832107027231859822713150971827305859314912727448091337064048251196912*z2*z3-83119096696748248640683881500009962325277200874859211599454588303425264092048175480931645282647847808006905056*z2*z4+28218598219195866058663976141809748100428185655431282402239773393452796065574283529519011912513201995923760228*z1*z5+22152198799960093857969372594763462022338597654007941131741376603743191962442610567248209416066397718437297628*z3*z5+15209159599279159517889892116491339618034913791154976889616066920874687363945528183345433092851099604162738500*z4*z5+31696336493326280368923790606739664837568371495264566892670880370778518622269225658751641150791166620713439128*z1*z6-53749249388823881748790220962222347401256026599842076921261201678644331246503995355202621866528418972619415128*z3*z6+61548055540497396488137113568231970178345100314131553186420943328999892024036628552847275790096149881244786328*z4*z6+166946557263742836483246670774696074425132506529746252876376533489354660098349453361176135715934936639146880000*z1*z9-845149532228539473866477028277628689621718952011856392456040848058961390719749502243532316395995851329181884800*z3*z9+684715366154384986009086512111879477350026934440754046780231580923175708428263806441832414506075236148226358400*z4*z9+45804004818624496805452322861401879753393026239833628430887220317899084212360947693524486068367356453207735765750*z1*z10-198528773018408504194628401304249444151464912852324918953467987573093298329536331750255335087819035838031881088450*z3*z10-2274553454568973229009090111034286981280235706493535555722869605467859730315615519399878004832869984894535950800*z4*z10+122634475221529229542764549558797441706461817422769932112247195257559450537665944420482322513712303618129996075*z1-411289933052176733259701560671821452942729150381751736755181263345216254993656697885827568551274468605772944913*z3+12033504279303142614973801543643178662775163695822386762760861238127255820572079282683148935507504782446499544*z4, 236041065341288143157499252533058867749752888240386108470710237675009984725433439050639524752999313701105752777072500*z1*z6*z10^2+11433513420361839367915118531222294830319376283690413162934427220072349919350689174747101563646322414728089130022675*z4*z5*z10-5087626662655560725218601152847825504687713895315512821486447645313721652838109893429645048417308269922666085032600*z1*z6*z10-9348693556761163408557281758880557798186814179151614008006670839530697140853001055392940024612944834558605606175950*z3*z6*z10+13666078827386913223951903191784954895497835126473325710623380529669953206553021172045923628558520112724093517898250*z4*z6*z10+124813447860373175423647721183366020673737528637178641687180043527915561743936417194159042286571450275024394968200000*z1*z9*z10-234801113207911432323566716826449347271806929093816543408770208483611362103677046039597039731184107095754871295013000*z3*z9*z10+111345438017081424493999505078085330517040157872756527440628840092398498426432105315422209764715571139355359822085000*z4*z9*z10-11694136751539387766553437490679118926894913917058802753832277551554925532765429964197025543839420755075367143638540000*z1*z10^2+22418043627168368483738306062464461486923212175751113664136738297902492507395681583609919640398063856190563261007859375*z3*z10^2-31793142406235013334490767058884961380498499145968817420685663989046308894783504076708526987699735669499274685944730625*z4*z10^2-24167735435712121624861126924638847565054436559784147298718919103769849185567022758480055348797055258850625711000*z1*z2+61520597845014839261720900946524841201665459156152489925709565960902900156225940986332925874680780130811385423892*z2*z3-25130071575138722171087440829775934493363770760973429741024838672989772714204156203886284690121532459268119795996*z2*z4+17590269550601381755535002274366150555145848946738221318294142195147450015406982616519452817063829263979967846548*z1*z5+10580943126523127655671545613571013864921486645786798478102161977251626282284863200675722868549324628798990523898*z3*z5+21685510505272147124369687362251961409935702154553766816253160302234051837937926800750397897456060391966648758325*z4*z5-17853065380597074553944413982150822751306641481476200121515891972563388586656428453361425182647133018438408515102*z1*z6-84331187943704735438881120129870276367931153711299106256881615714172858684330851198253648779822132013938355564498*z3*z6+90403069607750553385526545923453422312133137320011714535733244650780179656514272507196284672685908146916168544498*z4*z6+574805918297028582938177103354943847273503608504411069068343360235468536247887125694474332839419757387407533236800*z1*z9-1073613891324859326549320248687856306778890364410606052332952264660458283071008012268585514063887983942507508944200*z3*z9+504867630069457291414122105335165701239476380331171183853412234065570892348123615560928490290227765494861212317000*z4*z9-67403963881875413136689305975065063519326347670889913119267115372516040502884389533819523617441593502750925485737100*z1*z10+130481445167096315533178764520502146561399856568052873554669754865234313554522908786700195848648588641375212440950800*z3*z10-210560929752626541743983094595992962786161504607063956885692545243233994246820839923358871210946650828181110743253100*z4*z10-26734777490836416228804500717400517152115307516348335198622734627573481128085562683060791524588045522683028425100*z1+268476369900412180491006603771360961599551816332130741259238411623565744471710880886572448047580705106607569919117*z3-487566116630139387182960850334660860892885690417650870555035618403558415180957086388498310582377799162850469101671*z4, 1416246392047728858944995515198353206498517329442316650824261426050059908352600634303837148517995882206634516662435000*z4*z5*z10^2-35325825560025826690458139146727666594967385859350819130393235703801743062288056758505897473739756646181942758498425*z4*z5*z10+28688712800384041702553776890615061425838560212775033900379620822400712369620542158010650891511059099344583686390800*z1*z6*z10+29162624249494758896665293435136722676440171704306867075856099245783740833636472779668083086468614577971428468266000*z3*z6*z10-51870657049013738168893311555382463935964858358946073336834969105788499768248080003062270750542492669024273897300950*z4*z6*z10-519638314581020946819040822712696366535654489775283143910053253748274762035591499350093015384806020170410852408160000*z1*z9*z10+1374795448093004217502616657564614172747175305105712808957144167661618054367599352610671478694411551478132388585464800*z3*z9*z10-864068426859707686713337817713349031847423712964754731975921684267029287373730552990123768653210325980680106700300000*z4*z9*z10+14929774783509300917809253365919639041000421010281183268141379447660039008732931568643084768117381495402864606665390625*z1*z10^2-33001155814034691307007311904899207849901053539763208984739103994295983353829856187407347198617465423731626195059218750*z3*z10^2+140254894405012888016862110777102547580995951849223227120252073923123378714521223319269967304876575236020401232656978125*z4*z10^2+155455081811181413066154822828373314689650538881552914391454956774397557740551776513595698036980442486781880241800*z1*z2-272392502520480653498023052777032853832199901945522853307343579569418640680958668845096536633471668745394600435708*z2*z3+55037243073661296887169281784838174288786864621014958573584570885830571408541269668897345172709448955979993781204*z2*z4-66080337193181982483588212527314187151522720758035512394731917839458316847181905100603011780788751063037625472852*z1*z5-28497937792751142111885868859442308567922850668727112022892656651129083435497648420486123739218867764104030446102*z3*z5-85461683387378861471351956071963095658259241335026186262332382560391014335927680123917393608308276459951701626775*z4*z5+53612905878891928083453328430253780100101667677135516416668399491362599842882239593118028687615126574452525569498*z1*z6+314222117668624180159770576027233672492629351214578061512143978994950413773266724887654582170241861272890479730102*z3*z6-322913681121036755164858773079804774222688025485010192602631488580115048719808143184966635041049786362138718937702*z4*z6-2436160318399689743227726318357648988786152101378337662206201810138608922823032954119814003395791130420451740742400*z1*z9+6302727693911711472629736388342427301194318379798685282844665972847668616448994999546012901978650276475294410668000*z3*z9-3906337218240550731779793813008289648241057541792325877157152546246382795973032679811956630886947258682551780568800*z4*z9-14523136676100634494767351284940310469606681926222591934640105447447453139191690064595996866551221587781327628491950*z1*z10+146775576352849427609178570983813707398843366821517138568036820500884295113116628789074821843077987950328150975621300*z3*z10+781892199802629555056136820851976336101692148297061576407472578370157928431894861904704041588395355333300607523721350*z4*z10-469002166854124311435245729170678967643067372796103850842511527744687418620992060191716033780623829141973623966975*z1+737614171099936388688007253287260403652660343905341535909766946641539223011048113376662777719141770789473486280342*z3+1420073074377355453406403764717514515620058405778768611345644586159898391465499026157961166666718978824852549636229*z4 ]: msolve-0.6.5/output_files/bug_68.res000066400000000000000000000000201456710632100173530ustar00rootroot00000000000000[1, 3, -1, []]: msolve-0.6.5/output_files/cp_d_3_n_4_p_2.res000066400000000000000000006643601456710632100207370ustar00rootroot00000000000000[0, [0, 4, 108, ['x1', 'x2', 'x3', 'x4'], [0, 0, 0, 1], [1, [[108, [111742204476694970770386062008801530470380024665571741133492656257096936189717722076678713584183458357309812873052993353936903794753336783008446298385254546151346251251385606655173618777534868105745691308075170934034056436684117417202376487758364422528456338944257022491411703687488731903883198187046132602710805317639009935112364090723061743959725227077721237755152005180786837507512565377018112, -2894248640722357760543403480673571593720016104408994514810034966966213822488096701171500222670534504181489601750285836388880500254322483734631473751250710393108375133111260469459267636548934561327997650102427091236438864485797522130494354421023206481772779828077262105527705218066129685094474515022876045964701059699763637989572644600437554780338602600702456244075868743125105540297034826599270144, 42102931817952355955004855051674486532311780061130851169804041321565686289285662822020042130962884954904408544482823954028150895146542245018381289469457284520734105611983205414915258103543696778756759521694986428992695434302167753018278917553996898842457234395771252956871047420684898043698778298316951949800978224208983427190750672969035129496718853522859249181382137151057196884337286517749990848, -438446643159573867619748913444740887671048751069047174353067953724774831862116754445677471342562527334980961598980158347736649288552507040107783079814910417281540269657725400693694474913257143598717291934202367605827425705297809569388879201372336348006310709747517932435435206491668341716826709063793655622667421778296907352570761716460625799347120635680242583576873270217421091504299584318376007296, 3610160722659264403694891800074949385124367354281974988373020349284630600509026147874796595116041408374804843448080930677475269555432464877915634693387560754871976555852755928448088554360014790021120403623056603511029187719451171760350080307783158818231194237705467871726649339017999928034984248709252068818795473578799250101361712159590996353183040492913509824268219146268181198288038026576702528336, -24757779779414579276382558998032858330314487819966760868692412956387824819148084805556139374261446046435328123577015982951062249011395871734887319642350253602520950488876151011059460508038323892485212919905830149873552184668146314570202241617848799728693682127352541873217764894502611912634466310997562610097002751937783976566483879030094650515120378584622174005891129885278646683987766048564006474704, 146023605794157699213584353928548794806876584784133638924460485252230067172251415347883357875203927512672590091280142657200684918036619860821138841350275489618126776182453486233193180460477577465773258250337675725311467014137754771670898316273325934784652965888416665924880154596268606570684207155643101600109027800636244902971266151964784792000551417112074250367448719488757935805795579530835788442044, -756987669007828031816300797179855786654918648177550032332169866694420935167247142405973488018640932149441715869140216345752990841590143493840015504512895835603875636297883383072656742254771417093319794284547866881834985360033253120905302232134970061108616151611388804618058934466195000647379129297721656671108764330254465707787605106427362464155568967408881279794373469371842215619183280061288164123264, 3503946349146359322397143747314097036549193009600511039749981296319707986711832587203738874962220606380418159178982277795428818159567721039503627725404947731745753072980605315188888969877829400503491223589542409242827142125962975409759951024207399062581223280031526946284254833718366774100960763540588744089823545828680511291770054747302806711488157740925872317386884842263617136034408179938681656671492, -14657577134469192216239839757723251750976268188971499151936354655547063747143468831083870533799044898766137766832730783921495993356268809355441907464526328318842457971158757507714934546471493344044535171066292575757510866669925993987571666996782599347416650786446704274588672713733135916048299787762524341474393899265496636082259490554286888847531252179062849837742233986591824704466170476422155243734684, 55946065078103897889275383582619865669631289817070852676232797863677109389648746897791980998815615063597691308219697964893146913618133989574080444549795857234424056128083650639992149091303372656850020782115194469844745772035759339199940504167765144671655432676354422092093147980432692450821226326677537536885527630283709846230847745336890293130847083078751829383351945979810391244257871162671257750076725, -196387965819535833051773620056499310924860114973760882354524731333739290405084989245105224774771857894226814199308304324785567516972071946364291469001272674258846876833351766485840562677303877762085004770169754951423974990771164092433859667574673753719883422255396328204180523938527667612110297748217799181107334352738330095364295349981889352339756500838948396509532716567829780690803926675461657962365044, 638292861970784117069110558593216673617276135509616686224217779926044022676508423239072462045105488539973027094516355789834140866713259252715845362611113246643899679537830067531249349994418708683505111398400760987846351399360598827154949349847915943182385135244651922589954606380073109131644091006581000962788540555570284974733679397011815575755985433102989675328974878297871705875537854997881374078058346, -1932168399654614335471431913916876982869474311636805527339683674362185367417566102511076951352485004443947350223391742213089936719947547577255302843536723162780609736394979217022077067802704406484274288956551110962015462980464615747073116138577228785946756418722143768766573786238780887604302807394986911653482598666579723748824098347737237894603249533692683805498076428365251956427456139161589321311667723, 5476504090698452916528621897434791854833477772222379381446214598968327546690281671393032823310606581414341734401785719574372544156579259183404065613664947047090952522009282834102687024670071859557115578618806013539178750535897578125662086385165231479314018007732154302586641778601906807793540058347264068886424008538361864988003418998805767214459781858782900902334272419532475922988891898899585103181123721, -14606893421824475678894125772348952053832215003787092907962595414175974766748010512282971924381355444272066006300060662832277676588851026369447603735285864320124369471487800623031728351404246478597821906163609085764524549901356771805606811004409218550637882801826955589586457492378990820325454341867201756263305400145839625132575082931831395148912914023709769592686381766329418062644581492677632521429588528, 36838562875699090761552470646356407748697530476180280705223757160574208094561905745261569440356420454311712112885551462961232624298090163436337961526785572245353182213774967802013062049823024966451284726496695974968295916212579663534678714691135441662754262167718758724851036743960720638171988001166743164149678963809338661348316839397795777347605278502155115102347881866308847058747392856261208579808030252, -88273875286030501280388841329952998963117281812678996176734496532399095406427601802949909888218681287917330724042200017109449984660432870248750726476937662772287485665255659157727580881406587505714005857080056039997000224833641723758880755254726755683043679334403834960480313269338546111859006563611704979312663856773802218405588680186058701038135383360321379704842630377722320595038850578567718936900121441, 201968565252168031660988503020045107606371319157037764667142609702894235341384446253474555372660653726849037468826736767683117711738212137509363556159672200102486672279063489053996099860672538594868963926236744666611511419530646574123887716032581020768397866540250274088452602745561312777049348526620598702143112868296030698792629433827450129769990261236397150933367338909986995018775898705839411354037652239, -443442718714649744566556124214310353957312000575057882413652650828449667335683518153436096994648039037585846702205078432452575132544520045597141706708942021005097424209082253328348290494938112216408429652726184190615049337510240076288927477622707072173350561958945113201547925100274985939668047022506264509114167967300747180382637014910979812022747425501078104323604156421998000579407361191358739386123313770, 938965686245593489114790023691101857272312056369149006230647469437321487106833371800135745473083711144878118562675831365984020392374254967748197108204949492153817305804932384134885427962620364427094128925051887448359530805640489243002391841118961850780715995921799775512236940820542810181069407547229313551304511019205332039930558857090855381269536905657762858705919333248802306778753171726446781511748235476, -1926213598714308806837199306789491058396239524883871639718711043179874954176774040689205247833781476450292633006048477916047853995161253855776811452800501186536491000982497711171717794814814299578822635333444211467652335003145750001975910946995756099356861508580378685679228930572590058976543097858243901634309114079459237843727894751368746561696693732584901373743284188109597370788956395326293514945639549759, 3842306681522368718543017886911601629180434428515162462023642806213928250514876435668097976569307040317449499009592309479190581094860603211074172887189201139026673615320266585173345283066262592439895010351852475860411144531893895141897970738614191114709195115291393267714520251981169299318097046562953628224613624002430449551967612440248118317145762752819327716248105525046636925699862693342220519315156406397, -7468988400910324350668580760230524895417738796091653875193447840667851177093477068783275211671031914916607399301799558506561516350540369539153437401691340413509511151988814786345808802043095163649632209160174613658814051535713389981513354473849838878598013732777045149642382280562749028276912068134157362564253070345506263280878979773899516594556452303210411844237458393726573869979172875557545779299628313959, 14152328488309940028474238619990685603078775213517384650251883489212930881925498873529605665569550939040282635038067951414035691541547796633878073301287277307061023877070721856152307685388936092489323426213633128841308711821463984021365668647169897933617430100414964744208507718281252888636280315484266060369328777701730197092077926459819110508588615156170654477475093628372953770239623193356047888145183032578, -26091600172018651278537800007762878013001648316217103566286383038076028719908286415923204279001826570834533756183253124639193223530787223223363302182208034070263256096706950828778304891462937666832406662139945339735089497086374721817233102544032365376601455736100482998624563652508098381199567096505656052457112085277922320221954633686799303460248440696534635304943217394467363604022119778324284119043725194490, 46629661378527386022944411368968518135846371450069910183080594302129239305512316267366598359809745820654042871453911422199094148539624026205805889961969665473305259036284078612395740319391394831701508172267605369243714401582906075726548752152671969013462421936355155746512708271942774076466004028497093354216900910064100396048328893733247232848067026248367188217033030018615167721742948979501479424885445880121, -80359022309298660440798461913799592561211678291664440998637944126301277143876174075011253177667180171528056293715852287214942125625378356292525334621150529722694278317862523565222715484630435412393296793877267573718303340682044204003011732437751379724991123724241291037430477134049053671611959346859329711742902355649140524453165900023806850644629563433100114798179012741063873790363963130311833768586838504230, 132692887065699369069682760725809176606348139782930324782245726776266130603906093521353351910683907371282588809878015954383826513324683607245497779173444262152510127237353645816296814028265604333237419714122482394102703607942934329371294835368395301673309444908459433044939646323183528660362473689062498227825154766368361475344456654910287256782184209076303029696163640059090277130153551396896670712569413267012, -208406878835220870046585734445132186987526095104994038206384398577090576662663262629253099490208782235556315730853552845050753935895260931781942597983555178052515295536792321233839895700588714609964366310448782563472840728001183334270264297530139598046237421184431636998756677728653801446620764945390632941157280702106693487198027627629872715046431976123706379352835380356095073918237018741845218172035948685940, 308688365204987492019825619405688006710328719628659454089519968619124556321829408079413286948992171424817090740546663289688958365080871248424623987691586390672350804989507225965136065374334834872004050856493198138922180664406765211084548279225666367496209160502780432860802989787888123256464286440133433220193594949248957044284129069091528555002104444441822394853627089081397488589074037494744676911446276932916, -426653953773747004486571593883246191255176292146998784698766861508530976418597053192804141765665712313153583395989773955639962354789097597277950842339123507180760973702568794155067510090228922051660408225353665604388800406729813958843673201356838261026281644370763936808807341970200160681931091153530763765407742579764832367172509744994896967887698572185821967587275081284228823178594843687151815386777166941409, 542276071244951196635767229955110228881318348615851469102769822635966867034663861672550198758100652898905542531964857645793723920036961169614560291077228807541303372866383277827115788373287918991605971153412250552870681272036100293851773744697964775311541983252068849177327733084125338390918323362314256596586927934061974232986067663443484408138787452298466987752400411328606012475326865268386286140325261716971, -619080388225752516690883308848566207555777740062391607906133672552548551691174500969199039454629046033917984677465461030662263509172700219048609225024440880017142543626304316949708802490188188856520035622792008807580631579590007585466162648476161830994978264571047041231489323900710785577914133929207385419874651134394706118140751102712117242565080298825716053327164199218690846941273166737861045895498614047497, 606193152983856358661873601513551535526672113020091540100138019291246129141959560613411119859128354912999148520933583547292700553274452857993466792559146650779750717178334597083101626265416553835236033792539948355451827812663462994938719227357698167087499897847074917565948097219793444256631388889270284346156113180463187892044103373972998716193487608580888167594215728290415248326542465903687395821284992937477, -449120663169056415768776886563776049687052119194965882024781248322915965865927983598241612266030531336398530752949062505992695536952164681669014350781844153331403817497330543127592551151639806238589664466696301415005392433897617772864023027503630727890660565741175016947162118344545929525501846454859242739292088843177698837713771955460451942244288500237573972495846462177800388267006574396432017369052951233918, 109720479542833103480618642433788390369628544345135690420566559357614448496835742209668610206030267519271022905347062850941532380055460291609505113650223776818795487216468737664114026388790958859458537075887459862457499777595882821129986707469098994556724008895203628114012804594962305337484959466700591333565530129190868577293073563217541269894823542369411072611499010665574252473544449133118794361912482575576, 410150760522799624695485832542074361619747226989004100735886008244990501180936692787500293354417039717524272190593174939918091966109892049677145897256772779829740171671278203388189321380128184712614622005127015525792740791759950552795342626533071671332451789579451300351693216194405429393331075654014757901227169576494047904809087971946387760816935356417794359596695181485810011984919074770789618218746239870544, -1053888332786340252578051994290626978139652199465087580543228489823519151493582787328041555315619903205722593178170621892015886724354148643926512463767489261359836190108767902835323053456115778601496762547852041911979120566710017135222858436683186968160487006765341037404892860382295248265830701697165112050682968339040975668939355997099622647906818070967736802678032039018299190915278769957586176572907152008580, 1720285197835182259653785323974517543264546469431049316863048310954666910163946310482174846252516235704118454035178914600814325267994413999156040668031688545001816406582901109941081499852458088343117364621386628598807215362805617423377907216797852899905880999861642762262499515455694009414484088594377349500366330479027469462257703256345864122694291641048861527917170731326330830861102118240713469698283077343319, -2308540562509056604289129474800344897603024841467882840845381125698263834344710734113882684786009085759386697456970677363016885327206922298531603448613348430110673631280200654517882800774966584593359837230810177300507172472020567358891402636484278020941820639068123005094856901109953405884775593407152655371099727667603444681449718847251837380198967656271376758464948538343567383831665326711056695431468766443581, 2789948289807481835207007670553773601605288938699609296639537822737584197663731970135746198298971350200943050415086764002895827382864981835768937123841433782635026664620818414947884348205999031287589456526726762370699158604071143896659954862997766624571496359232319857252338000268782088644258311044628661992662208791611596606925015771477528403093790632018842011854598181037621798082897364691005356146826746731973, -3273255873617790558292118572036953742739686189598647188656832266252654359767321630372819094600995106430485068154334471833290677630232719483937241709813343778313216065668091731821026818019157038567378086272824820316828096681262423908388043800245256621881465510968825610894488850657185241557997655176544410801236298523140163473768415753247545696745794468298941614716277554916047996146238039118688924400107766521513, 4014403563326237937479940340248569944603827633829805986413985824042597620718755626951478495230394519582430622105576180883540055521085000527618589896984611865138073668727470239274349604148473890669209816102838107506262153558811447532670538480536467367692021200210812718350290569708454316788810550166899811301705903058348419926047570834355910780386567491528199910016699005860104819673260679376138923469307127382867, -5332649142835692621295408802927752073787786607193983377994698967781710894899610782861748184411900845508202123161410803346397073731301685269580803759913050376832280657937211266714942030077559688648604955439976435248333209067532198970414947161821733658174843313580066481506376437501183356205694756048544377407961391185372796335673494162069302869742926307265852123584121937013220894510921501008940660510810344236701, 7442936144836807753751358403204772954143405961995299803493481197943445740019015342237668727722410127275288405980906658772261015448658806356159550032450829858888082269021357455805095314780386118870609344208291826708964134937421966702705525464656580752815595313126568004840800838970330202986598328108714866902443528857696182747108722639199897185278514011344462946988386621689010208967571428985935657096675031817230, -10283006113805323361379534588995760346084629088537243579780368573976588514175751802481082854890042755703311197774808549251712223921563494368350087793218112488704655921857399452310076784562247640427084705210384606649072963038686798170401777044358976233311586749099046554040647952616783652995289547994900390127033488822148210870659565066328586058697439794122982654248368321177717168839684443676123762864519145381703, 13460063438534183562118121984267659285894169685615516830468039214416512931282285113904292422356213955572265947036242167149986760916370932134540766312277024611333548400302533558773494219999298899266002879111061439096781226520184358755670908626545529499593584933225643879359700617350148585042665879861548054022360613815569716388976167677979252610616067650324394043491361656758209214612857966413303639625418971440154, -16415071959539632113200599317810753989026541831679243230421511825455872826108531254022697123297897481772723376150976854463896937258933550182841818288132463150795884914654114354153837150572797632772978660955380445594800459692167434486314307442401209695085589719076365094706362563639415992214238358791884438472685199555011827007856013983661062614317595244296561860189696286832509473038876740660313370931100860463786, 18783122284259310028534024528786607886783308819318528798039053199937865646354140792010045878826050375453544053859009241387165319206024575241564578738957374416661379565138556380531402605599819625239501630315105747153881717774807470128389619877359468130801679792185219535460017981669941472157475985790139615445144945743694582427388006519106805229287594650686371541064494029008100346299616512945437058102991086916637, -20760756407710890572420997312984713151796014253592526538460620937633729249604144193620646117773169870947397166171702960031596039094040294923650485515277612807640894214495204493990377611057226899380903819881387246060019064255003896673455027953061546716685904872105002132708074702847551364994628948090047343662187593707047103440227081742545934400378100252515336708669399129115158394031152841362831329021365415245634, 23183167209819911837252504099337516056411262384832615944599519515485576179376913962421523975657446176251573228938501022188487012884221777378874628562666525877661169093019893037031328287895198348865651102587967522603830908127952912386246903728774381419682521981867418751316428191689138867171460509355307725295493121783028993998265150866574197696544335569829827769060119436786670073018978211500353976380419045527809, -27080058970863465715997580976780748813663577597835904800792647100112232413635460937554305812529020526598886095572523313723074067372205630504500181003125749930572771531664619612689669994690515381734336400453500805657005084854436964575045147608664310093098286317153519673320238708646213618710126713480093352532590319066964812143791886186889146355062697326253523425822250745299024698360853396729908450082597398527828, 32751497649839803944043686653653680014538410355688077261707580308707198163884318971781193925730683695303702252717441692078481397185842948100453586272098839288962040969714871686613829215842912467908074971181826148917430270898942914986323802160994728572894324840265271432610615892514730358779334834830084706104072670225935931358718091621516020677039839714692358725234187883494300756498391675705637794011460812210560, -38773367180775118106493584847202862985451047471063665869127357221516341330838136552491294245563860181731026098449603577401144846177948820525686286566504969703391663465333430684635771102555992271577904634444379005379521234639284694147741522489686605954305591682988359798905513187028505540829103738483192342595958424329555187625751622312691526053621587158738679443505771278693987082516344514947254127730191956709799, 41576653191736186905865563678587140784155240095834473141766903852672726171952690177176919905666509404269466309878950618792701212535818170524107951954256580037809229561924908272438800914062627684169565704040347657191573476567432896991830265669594004082830469666068833237975918323086903442323983930106082243069536340135880781159740838533720335531495427800109311681436002938738189056072622165596955822017228164182812, -36125139436325717763122166341376904141478352359565986950152018080369287684117119098895821878987707454395431314173658889924270580202531850084639106576835071436140242331266118874409596905430488611483784352655310359156832647392330984368772618632547486257391102707012391392849002837110779320681005638960093478561364757194113152849259492050947223396067883858154502871136145684106097869718154532284863974433747352085528, 17697409548403542155262897875861443559327136893670011408163224330240728040687108769516293420354868336903260252115300165383072825260427892964175485485591735591724444703123026284116736824889313940523509641270465088359202065430649707219493881189083519878826281456863516709840454821544865642503389623395635713388119176057917279122859126609164495808368418254372755135191782620825609955693994855788349470797759533643840, 15916676940383923643670740690244869898908326004659194474834606144984680332067752107221463101870428985384187336845539487120987026461172608524180972874541047416674937341579508516865544710383723639300317948145870271173994807482541015995744743244569887786232482645155295941393432484696060862386231009084180908026353907093074662428274989473806512892051623327902671221282996902932946754850226493459437373837751481363233, -62955857310168348948131544094093855464284269520563726149759653305342365624692797159537670725225764984566573504615724636566635215895918804092091464454027003549248095334920210346872401685122310728994394286658826702138420016105802534381332252062014127005848100185867966472519919293834780413548445774319346460521163391103752943291108623149766718344264525855666018409200463022783622397109678578040309058292115095156407, 117974817738645589098445005220079841231416373741218420572131495316181627481226448408487409409318859839298957494639894422490740618929443125034476605256648093675330690517571575318872113898186675119824736377432059215243055545778936848356631697135934199036919972389822918283986640427425655998487821864365144183888697379929494533259764858287861167279238774906148213522351928421589625954653490264973773407676032194513685, -174092221972154462893387643773085544803482039074317244780783707777321027096013020908225364021600453191899316992108503142239738512073193402908171716685518383400816447788437787855087730595673550864983485017771619026882096722912367330807093409859524382073752588563259690069164571705427166350589805394558364595729245574205968487151836622531078544586672612182210927797128099238181679246133828757585229048933154525671605, 226314671390172229763124767108583275409750535034741444436762690592498974398793310484071238626498006135377401733267749377296996905646275627222166956416244848600768694095220091827951578480203458483117443912311649866804198022480586572775941859161185932554165178037257284665365336262142839505333526766330046299956916449620934277711388726886377505126518623430787522052616347069350456199356100724861254929814973806855201, -274272634995534189045121216106239014929104300400669399457769148884175470772081254092080365963564155374459220483787486082145443919582065596061379651416106508822824886337260850342255305376600435102505950141159918212750791741639552805071323451708211345448640070755396913168463700944354825510833518090312270642532889448030939900897035426836306039818973058672979841742498683893041494040582361389229919166279911029351480, 322766052162854046128323300272374840162745752729707184830824672747550551002119996221368850329573440565759320309814636645208876579674529777473092238747609716134390761424061205998527788092358089797952169498496172146933656614057849816373211247251259446823053495803960325730070869775955285536154854511540012353210695125150785946658640854890283888224149221714204975432552168569545577951964726786702640772111019543787107, -379499515647127028929346940287818417929274084502738552968479485233541865690329601033645408737178604334372735024919602823574274747150033151761425147514667038598261685754333597945921841718066199631190921288061039717180186790236183684581163877503335202786216639400297929652908958820981409878194499191620928134755392472460355299236978363850832719027280766290340144499685166726305543136265989266493222849942545976716015, 450825804780273708317185993096022401660874102566514782899238940191280229938521269167239285917020020012412616717262227298978111558375589661331392309824564519940562716906381082524962141420500501132471347388863926667378273188231294695338903508543776029662975936416130288127339342493692449433971176560839561926656761238704720239914914573283372377093926753684140749235599114994898339675548181788485828351371154931063580, -537439828854456625088377073820458467096754323073077651586550515772144290745634840730204080503243078022979785075950757083989006541734103092967300685290559186600475440773010543068120266373574896721206424578462182101670737890733596243929304802304059968797618360167421169886358422992449787751909382308773584869192493471672856083643167249765420493225960815690522004992928619552433639563876394112126608170576805519607494, 632135925766174915876317210711911920154129678023023924445484606141851506359067963017599119338020953274094437247381245674907669693585300998889784444665489277590212700134540862435572102001896220035471293279711373252747933046784744083114908095969295943665128733537402687083846664968087266932637160503572499361282276974157996061465502057624172359683252125857782722960134386164682584486729646863657579821909137044336629, -720837542982939783812741905162434146430144017161259013873378821682259950210351630714895407883582964996970402860304966600071376230356984600682403913857377587535855405311494506334979523783238109806149646990030765002019948973912649573675286956871877818725545123402116184080728075667317985151179253714929818631522479496196437139864106872611216537012395571893515705492208501834537987497487054643742337948223117573674166, 786596651499055872654541311525692196335203636154838528020413918048249458967233424731865995920320793912921567533906464214288569483136899379531616890793582278705073020097345873101337798541939453025914567071810590331111054439283031912441851294015695650724182418058982653227894045737294565977969134602056843979550342024134772851087772000650793556136998240095051700843218839249178150091009453679426400027952698815517059, -814923349909538192371139033065608664747902982160035362668004311612296908668642958389036291117251921527527463888123259088173544436085504860243156261968802074337842915170933371964028681326172337481521304370442696029224903750096788371461552692519095717420080929164534181776381880945190815310079617027051181135855635669276713781210420942284496332902497270295013587119170367492851480760855960498201088826342233415441005, 798296005680659382527315931070660599092338953429909082236365533629328957810111798989676978297615970497764028932869999101259204253091442770163643566298477024221742233179173289656744700520003449051440828003169999286779485074308623441710172152631067873245909695360967809562784720582633000252843718568264043203420960856292267729383333856008980688119171747802683805792259993655861164388843541677509125612255996269071369, -738197877809160744216182748914526880268916162929470118791319848381476253834639657294580233485713790051847073621924134279147743911335284064068599639772657937686813502264835266646131948094684635010954317263027998380908140176995512890582370377901264109039238311935211326886986526896497547568483666134348066835007751211927815073843359687512803584620484348706925479772765453447036754732360716568432875731601424039594249, 644186097110745649118573872644417534450846371499440589034229508413707673609701403942427955380202802054492215800865739999793247376412738861065651701921071774244821970945594541032602117462111732819903730092717316673933955611515958840176254979171321863744961480939009524900133315956973946578436933795429268665417432732520124421410245761620341033296078078560950713795633820014233668541742175357715345497287470808165857, -530704215518390733857239080658770494236345686834971277660762067168047642747950084200237039886824591790854533014829244686531565898783375347676506973307713738824691935766634829299740151354359357686039056222831001072119636561910619551228998480980308438344412333326359051506536787351260707868337160463405795128219463476839032175156428870582278578844190587509069960507472926310795451480694810983415167916360147920051201, 413059864445636434886106644786696560276593433851378261000454924159327717266833738345677514482949812286205627215915257223032359165246673295284186132009655648752465892952508856920350874790941504837291483730702198184055408392798604299340796886695858962270749393485797727441297344010362245973760453964172751716646259737486753431077674587404601724198357936756985367551496173439453465616648353832246648405176950578565239, -303995952083362486534280461097191422491268517870155117944256754445540181702693355527284558825682764242039528522757492190130205997873698995877587429594801772784835062798427226287170324914915581703726633910163225867845752263762408602672570508669757328777922470078821120429667608401224940114133213725333563658708082127422108705930788693853707980036744519694683869225683905576324378719416331316994472052182166310212998, 211742741632607915760621125315074919905197109399105958116326239855924531939606507868520698711341463027614242638643504351258637317548747070805130887897504337179602796908946184175986804925978889419444813928373760436182940141836892080370166044904567128831189521797033728880923882220764930723285440349351360391899866880054900284397181239302288980615943803067166847707605977511921992429343407287097366896937307131052009, -139708992112274049535724181397781035801763589969179409822308595964973663028267585215156153470309929251733754928486415864123453949554208354018762341430236219869014199745578151885005418881036440587662513964689052518352110636194214682493892495809985282179694620489824410211667632626583009570268005377568708883738203456151118779152716406463430970679571500743360713428156243849488423093073705576160380980865692321922729, 87396348977624100275274674872802895425694785508152997208110145293939108136494465020679152005801474058508490985237409277089468332298490286222176964466298882507746355948337762342099767039119805812855145693957417007253504103397407833276929382432859882265533287576373571357958739161646938415924549773739395954208637385275573748585469235650463195131974038423429076451327727233174733834642760334478408548767960526612812, -51877028936447598610514288319292428824311242600619909390868213276624611638314282521516874662430767186611332908467235102307164519180057473639351268278574089113673290444647597380239612889005095337543843194894570900812813809172011757957830158352787559721648495654613379200465391452074859058013269718947143205570376911040830089963451152757431624122264970412058723481076127798714722881419827388942082015646499750663472, 29241503781872175284016351110785196238104245197341559277490944260137724378058342586064145955752954686102770031059026118131200331929483643994665824666689439553186731962992694685040830174582667878598654237609049681619836641551304731873985063344552599818141717409238314095007917156367695217137034371866688694395008049961387870181023723268793842402288317837305947533187626887585010784628275002222739723166050013413214, -15661970714013433700805857636909649935466932323137867083763200668449810476931399345026082875304836600749399512969768000220949145300391018204025133565280078584335739851523854494586188423164614316093824599879042122335138061413298259423868517203712589694608844146128624323596037466041444451778712278450536278291208578872727858903083546760079530186394713515805304204643619107913050237315506492967449092099336522074037, 7974638038642459083422649732212098523819674829541672802002116856237658628617719179058164129869147378195302238725826547142468573047003785358846806207656163541806185586135716651576497538484568548550525599599415520796968835259538067925471959954886130219823617566140850237098339691336654611713726627837124017807512896763230551769846415519906512605366360288831087692065386835996303440111408568461084926789556484744434, -3860648383428505396537721774074085601567231836702561840984421855842798369166972322046802381850156612681881670538797852036430589045391767721283147898485002808718111305753353521434798946851012905278968940497636373332600220126539677193271556025692471843743888777973902286259009547136824949824098844451751316387267570957097316476940095438813650490940344007649266472790488030772718989321889079614705717464020925839769, 1776548827027411355208747963726667430933876841450282485328340417923087813312123652908950780200895527816563775713884244875994188136652392790080246809505690742626786253187589839497582436840367270611337670461181700656847112604238144092850329455558671096958016268877831461920349722082492314017913544873703952826873377146326508004886575907123329337632750473711961230437869606923252255053882716173517910950155781004755, -776431072690816312384184570827792760293226146441963219421896254853675682510814221519140822571727273670775757558540701397591031325391641092674168921853877741741204983324327195471794938848149582091591653579140330376540141319152296311406278255533725674243557398070150235652866637608974533330949499663731610112438472816295962720674440787898288558092609693095488170724793463098611806204807047716777874181051406456252, 321799736774384369647596644540258249940017538877749689922047661834526413649224084503423414494134881635715911702365093567104350023370281316683844240019479706574641866857168750432196433759729798134633400190052975841055274700381155651012731636188262626653001907514091854502625151491611283070212829332455816867831900534721789681605421230174748528824051863855979179228344912186285066268191259822472690311081398358590, -126195796189750790228252373009992200086745225724802528062126065311119484169993819309531260850879396198289376417186740079038707412028292559176073161953025394327702492589647954237467243182491197016654483383390959553183378727194667755416852748039048090370529583074698346196726885476977942974991614739841342874453002481289210644199919097741124332914582399555794665099589334575776515109814652143375949378232397602741, 46682815698491638884503496253981177352046455593738546675735976895827823336388501381835682273353116019090448290987389401460293802520873055179771830776807027507983892760872612225254732057301107911255655445217518486219149897002915093316826159498142219255444649249240050076161659377332643349442018624982453696124729788527082981042938943704556942041410241909874410932183428360551350464303551145856827121414273457719, -16227929641814794416071869518183786573365210868789271610813735530850002463804743954251494536918302207680017394926444777255773060685218500916443525107130555873280433299581276210999529829670439676856724502564792340464410328161035881971524088310845398900511169705254785128016930435549905514850834610078387646380477580533609252243637466125235113986418619502036900203531894913314706823773299108883639393327654695149, 5277047517380186796563558225394209229017775228204966328331027246394421755431431891726138404660677581215253731704916326527091949689176666246569470019571701196313109220288575431556177358135815781654509489205482969408335840677909949553533296666285424961384747183055207320076258682863290384236426188577215269391490463086681866561992912075104622092967761585250832109319709927946662258194476553320588374552637474443, -1596918404028779875908551596884940796688074832081159685611559455297584278077211521313552253684342227140792874881230366851261413716376703035351446508978813864036743411961771870056113194320021409982820685016931938656889753144351322003548603324070368326872472812226623809046273268671668179292302720579189083766479198408381065649655343558226671863546644022972671710647375441233269526585000674636317875737853165170, 447110480580436671393068850244058079279035526513100289014846860906399329360371997927290786444034289578439510688445838381341176014859314364107087773081537955215123950906742091320569189777460207854333259011185551258770855000073340856372877725447256506474601578569010793101258482228203595715086420035866933917061581874381310587212026404875927420289961119110193826653218647764210149852316918137674911211092543504, -115080649731161451289225820351358347551086719089697329495406874167899271214768249859525829307355585349794231060387435423897163914112869016415009943443481099711487901624852486237880990663980050411965293627003784737405912784418414074674197579130197002276033328106056495543204662093833467352105790394158195755773280070898040861834126558092070989591267427746876451596632574290720408227928613884456384013497329236, 27038226932340425817707223849838218196280639129254080942481443993913699041521210333463255336105972430484164390591823861835026988211917471994060647387791124605236016795691342766035356935344694462598294469047013059730399401339447470242707731135947099018531085156023897518865207181173268146347482815703673464774330720575730145614501014687075548581554353549717267779403194618850073550294333753453661667743410296, -5753659123871897468201004604992990267046757643234121817185794121010517130545081612976647226441431720584140529864165229217519333410132862847864288325987874831327951254599880749517646482376927388184555452005965569192336189308232841674617339382759014815510660046918026092100274860856203193536346764438411653170378459397827910309961825465369008675866906632421166450323202777612061767599781130718299381570324066, 1099220650614476192477921391041357340819108848497435342988376140491883719491587089747757319949533964626521536542795737370482532890369883154261942030845339725205084232948524679091939234186991398340373593857633742948703173262108072800446203537844358855579552218120237624040726653669157194115800500431028308842812277218759831265841821748910863761324392684300492555310544005154073236001864191604528997060433656, -186654621451472038442815212874461613899519445254901106716083116372535351738756713132436497127166369237451686059584479884958942985499144967658692849638811363868873860918544286610831989208053570326286103811946885033472771498168339841356646385116845725258267647447803030288056671365274325444492758605896550955474843403736934025282248832638522483670713338086160387000315251362513581499935370236646580529146862, 27842406311423281756076908992168242994275749394824832918516579668048180736751319610212479377947806697035469507512106808466964915643306561023882215795377794749259895010032421270907843289007751996634008216830690716384215880356154035191846569779330112472159869501750693298554099994814106416731041194085989711480430214043267513929096010389823523192537211286281706675919133313378523556295144481112839888414161, -3597251081738586712104717674596107634968320860892599497917215601596387626879018119801182216424048239365705159783114013094502848080488096170676590138085022795543751653619355201386871418075027740272453706445520770351635532286441506906708354376438545456727387269076996511157962979643846172130949408060181726787004805617312283404865401984430688110571712578571338103566273179058351321019020212057556809795476, 395606236989522033085487346008161441229812014558813490980653903369226778236666110207121079065563382550046331835762717494147162501228815406765179970780660968303348828500533124579521244811175977289849740236221514410132254434758540002761934738051458489543881664130291743513585577425544384724670211331696377571947370691692085478395373430296225861024942793157063926653436199780217862477215554548336332661820, -36214016652432717548386487019804933991359417856380476338461924870605573683440643248922690414068224396268973592364574631722128578086985426917861549673218693215967497603079705365433446297867518053100979885241360049631062243030245635101642446166837175685816962008284950085207969484553413284667740281571496382106192123313482509010874027507432640719278390354244314672500249602400982790229308164589984859271, 2677797751327829297218864144312593843625504101536905313217394271872391621573282707595492401659218521409002929173905037233023070993929885348495817917329149360676054291977890099207468710147810348097583619301108777651048151980401651543470904763357156100997799601220321499243781495293478137327135253372069254422602698084394612799293185088726829297044563259765098273372005349970275200175433739029010955460, -153237500617488704969781805707498750415164677885202223308166460815648242221237977167526219252531346502308052897676760701766415676822657509587500413451517774269379718047459929933364812054359999748254619057123967055053719783348473771245394382066013325538096989986080140211678028279702525426075729223011200343056847647494184430681716959591278995710317315568454905972874218296491814080103948487630563875, 6347959468796299760896390256197014904954398329599770404377865911696500977170656858460201292021061192704472123809616223978354636025892832436437774176732428437708393109761529659624439281843259159069743671209336233061533081179691069291970086445071140084513099478563396116803215341849211948236215544133575468070246914280812470488187955455644151600697060839454049775141486527500103028512143018521468750, -168781029589319116774195354707999469829793341773980793323502004572966403681849295259089241196380398953377359386844700967265324094329431384130823904831282766956369984831977392046874681896822650788777315729377869772822850000224391117368721002871436021703756043997378061489500834773752480953177379377135097177850338996140643865994549636273799721155224338262038596219800873634131386441158412384272500, 2153940994460877042937752842132025683239025039311017437173614655171629842346417212965527205651824619196101056944392801717313390506780103420890465069125913784222920385006147453869406243368749908104286645100405413770977323814884652665746630282663636568535302131972451875015921178059080433217109286117856680947708932675125691849833450520540617563888843696140976210460950277796200352682383484825000]], [107, [-2894248640722357760543403480673571593720016104408994514810034966966213822488096701171500222670534504181489601750285836388880500254322483734631473751250710393108375133111260469459267636548934561327997650102427091236438864485797522130494354421023206481772779828077262105527705218066129685094474515022876045964701059699763637989572644600437554780338602600702456244075868743125105540297034826599270144, 84205863635904711910009710103348973064623560122261702339608082643131372578571325644040084261925769909808817088965647908056301790293084490036762578938914569041468211223966410829830516207087393557513519043389972857985390868604335506036557835107993797684914468791542505913742094841369796087397556596633903899601956448417966854381501345938070258993437707045718498362764274302114393768674573035499981696, -1315339929478721602859246740334222663013146253207141523059203861174324495586350263337032414027687582004942884796940475043209947865657521120323349239444731251844620808973176202081083424739771430796151875802607102817482277115893428708166637604117009044018932129242553797306305619475005025150480127191380966868002265334890722057712285149381877398041361907040727750730619810652263274512898752955128021888, 14440642890637057614779567200299797540497469417127899953492081397138522402036104591499186380464165633499219373792323722709901078221729859511662538773550243019487906223411023713792354217440059160084481614492226414044116750877804687041400321231132635272924776950821871486906597356071999712139936994837008275275181894315197000405446848638363985412732161971654039297072876585072724793152152106306810113344, -123788898897072896381912794990164291651572439099833804343462064781939124095740424027780696871307230232176640617885079914755311245056979358674436598211751268012604752444380755055297302540191619462426064599529150749367760923340731572851011208089243998643468410636762709366088824472513059563172331554987813050485013759688919882832419395150473252575601892923110870029455649426393233419938830242820032373520, 876141634764946195281506123571292768841259508704801833546762911513380403033508492087300147251223565076035540547680855943204109508219719164926833048101652937708760657094720917399159082762865464794639549502026054351868802084826528630025389897639955608707917795330499995549280927577611639424105242933858609600654166803817469417827596911788708752003308502672445502204692316932547614834773477185014730652264, -5298913683054796222714105580258990506584430537242850226325189066860946546170729996841814416130486525046092011083981514420270935891131004456880108531590270849227129454085183681508597195783399919653238559991835068172844897520232771846337115624944790427760313061279721632326412541263365004531653905084051596697761350311781259954513235744991537249088982771862168958560614285602895509334282960429017148862848, 28031570793170874579177149978512776292393544076804088317999850370557663893694660697629910999697764851043345273431858222363430545276541768316029021803239581853966024583844842521511111759022635204027929788716339273942617137007703803278079608193659192500649786240252215570274038669746934192807686108324709952718588366629444090334160437978422453691905261927406978539095078738108937088275265439509453253371936, -131918194210222729946158557819509265758786413700743492367427191899923573724291219479754834804191404088895239901494577055293463940206419284198977167180736954869582121740428817569434410918243440096400816539596633181817597800029333945888145002971043394126749857078020338471298054423598223244434698089862719073269545093389469724740335414988581999627781269611565648539680105879326422340195534287799397193612156, 559460650781038978892753835826198656696312898170708526762327978636771093896487468977919809988156150635976913082196979648931469136181339895740804445497958572344240561280836506399921490913033726568500207821151944698447457720357593391999405041677651446716554326763544220920931479804326924508212263266775375368855276302837098462308477453368902931308470830787518293833519459798103912442578711626712577500767250, -2160267624014894163569509820621492420173461264711369705899772044671132194455934881696157472522490436836494956192391347572641242686692791410007206159013999416847315645166869431344246189450342655382935052471867304465663724898482805016772456343321411290918717644809359610245985763323804343733213275230395790992180677880121631049007248849800782875737321509228432361604859882246127587598843193430078237586015484, 7659514343649409404829326703118600083407313626115400234690613359112528272118101078868869544541265862479676325134196269478009690400559111032590144351333358959726796154453960810374992199933024504202061336780809131854156216792327185925859392198174991318188621622935823071079455276560877309579729092078972011553462486666843419696804152764141786909071825197235876103947698539574460470506454259974576488936700152, -25118189195509986361128614880919400777303166051278471855415887766708409776428359332644000367582305057771315552904092648770169177359318118504318936965977401116147926573134729821287001881435157284295565756435164442506201018746040004711950509801503974217307833443387868993965459221104151538855936496134829851495273782665536408734713278520584092629842243938004889471474993568748275433556929809100661177051680399, 76671057269778340831400706564087085967668688811113311340247004385556585653663943399502459526348492139800784281625000074041215618192109628567656918591309258659273335308129959677437618345381006033799618100663284189548502507502566093759269209392313240710396252108250160236212984900426695309109560816861696964409936119537066109832047865983280741002436946022960612632679813873454662921844486584594191444535732094, -219103401327367135183411886585234280807483225056806393619438931212639621501220157684244578865720331664080990094500909942484165148832765395541714056029287964801865542072317009345475925271063697178967328592454136286467868248520351577084102165066138278259568242027404333843796862385684862304881815128008026343949581002187594376988626243977470927233693710355646543890295726494941270939668722390164487821443827920, 589417006011185452184839530341702523979160487618884491283580114569187329512990491924185111045702727268987393806168823407379721988769442614981407384428569155925650915420399484832208992797168399463220555623947135599492734659401274616554859435058167066604068194683500139597616587903371530210751808018667890626394863420949418581573069430364732437561684456034481841637566109860941552939958285700179337276928484032, -1500655879862518521766610302609200982372993790815542935004486441050784621909269230650148468099717581894594622308717400290860649739227358794228762350107940267128887256309346205681368874983911987597138099570360952679949003822171909303900972839330354846611742548684865194328165325578755283901603111581398984648315285565154637712895007563162997917648301517125463454982324716421279450115660459835651221927302064497, 3635434174539024569897793054360811936914683744826679764008566974652096236144920032562541996707891767083282674438881261818296118811287818475168544010874099601844760101023142802971929797492105694707641350672261403999007205551551638334229978888586458373831161597724504933592146849420103629986888273479170776638576031629328552578267329808894102335859824702255148716800612100379765910337966176705109404372677740302, -8425411655578345146764566360071896725188928010926099765859400365740543679377986844915285842898312741714131087341896490216598927518345880866345692427469898399096851059972562813238617519403824132111760163401797499621685937412694561449489622074831434371293660677219957150829410576905224732853692893427619025673169191378714196427270103283308616428432201084520483982148478972017962011008739862635816048336342961630, 18779313724911869782295800473822037145446241127382980124612949388746429742136667436002714909461674222897562371253516627319680407847485099354963942164098989843076346116098647682697708559252407288541882578501037748967190616112809784860047836822379237015614319918435995510244738816410856203621388150944586271026090220384106640798611177141817107625390738113155257174118386664976046135575063434528935630234964709520, -40450485573000484943581185442579312226321030022561304434092931906777374037712254854473310204509411005456145293127018036237004933898386330971313040508810524917266311020632451934606073691111100291155275342002328440820699035066060750041494129886910878086494091680187952399263807542024391238507405055023121934320491395668643994718285789778743677795630568384282928848608967950301544786568084301852163813858430544939, 84530746993492111807946393512055235841969557427333574164520141736706421511327281584698155484524754886983888978211030808542192784086933270643631803518162425058586819537045864873813596227457777033677690227740754468929045179701665693121755356249512204523602292536410651889719445543585724584998135024384979820941499728053469890143287473685458602977206780562025209757458321551026012365396979253528851424933440940734, -171786733220937460065377357485302072594607992310108039129449300335360577073149972582015329868433734043081970183941389845650914876062428499400529060238900829510718756495742740085953602446991188763941540810684016114152723185321407969574807152898546294207754315853872038441774792452943227650368977567085619338977820617946644055460216534799688881674798402973839472417461543055711199009520976137823552923891451221057, 339655883719438560683381726879776454473890605124417231606045203741110341166211972964710535973669222536966783240913630833936856596997147119213073759230894655369464573049697324547655384449334466219743762229127195092191409083715135616512776047532077550406818322409959153861004185238750069327270727571622385448863890664841524730209870235035658652206126763748095707459402247080950890485750956640545149315484392781872, -652290004300466281963445000194071950325041207905427589157159575951900717997707160398080106975045664270863343904581328115979830588269680580584082554555200851756581402417673770719457622286573441670810166553498633493377237427159368045430827563600809134415036393402512074965614091312702459529989177412641401311427802131948058005548865842169982586506211017413365882623580434861684090100552994458107102976093129862250, 1212371195841712036596554695593181471532005657701817664760095451855360221943320222951531557355053391337005114657801696977176447862030224681350953139011211302305936734943386043922289248304176265624239212478957739600336574441155557968890267555969471194350022970345234049409330415070512125988116104740924427209639423661666610297256551237064428054049742682457546893642858780483994360765316673467038465047021592883146, -2169693602351063831901558471672588999152715313874939906963224491410134482884656700025303835797013864631257519930328011754803437391885215619898184034771064302512745514582288136261013318085021756134619013434686224490394190198415193508081316775819287252574760340554514858010622882619324449133522902365201902217058363602526794160235479300642784967404998212693703099550833344008724592339827004518419511751844639614210, 3715400837839582333951117300322656944977747913922049093902880349735451656909370618597893853499149406395912486676584446722747142373091141002873937816856439340270283562645902082856310792791436921330647751995429507034875701022402161222396255390315068446852664457436864125258310097049138802490149263293749950379104333458314121309644786337488043189901157854136484831492581921654527759644299439113106779951943571476336, -6043799486221405231350986298908833422638256758044827107985147558735626723217234616248339885216054684831133156194753032506471864140962567021676335341523100163522943570566977315781356975317072723688966623003014694340712381112034316693837664628374048343340885214348517472963943654130960241952002183416328355293561140361094111128742801201266308736346527307587485001232226030326757143628873543513511326989042511892260, 9260650956149624760594768582170640201309861588859783622685599058573736689654882242382398608469765142744512722216399898690668750952426137452738719630747591720170524149685216778954081961230045046160121525694795944167665419932202956332536448376769991024886274815083412985824089693636643697693928593204002996605807848477468711328523872072745856650063133333254671845608812672441924657672221124842340307343388307987480, -13226272566986157139083719410380631928910465056556962325661772706764460268976508648976928394735637081707761085275682992624838832998462025515616476112512828722603590184779632618807092812797096583601472654985963633736052812608624232724153869242061986091814730975493682041073027601076204981139863825759453676727640019972709803382347802094841806004518655737760480995205527519811093518536440154301706276990092175183679, 17352834279838438292344551358563527324202187155707247011288634324350939745109243573521606360259220892764977361022875444665399165441182757427665929314471321841321707931724264890467705227945213407731391076909192017691861800705155209403256759830334872809969343464066203173674487458692010828509386347594056211090781693889983175455554165230191501060441198473550943608076813162515392399210459688588361156490408374943072, -20429652811449833050799149192002684849340665422058923060902411194234102205808758531983568302002758519119293494356360214011854695802699107228604104425806549040565703939668042459340390482176210232265161175552136290650160842126470250320383367399713340422834282730844552360639147688723455924071166419663843718855863487435025301898644786389499869004647649861248629759796418574216797949062014502349414514551454263567401, 20610567201451116194503702451460752207906851842683112363404692655902368390826625060855978075210364067041971049711741840607951818811331397171777870947010986126511524384063376300825455293024162830398025148946358244085362145630557741827916453730161737680974996526800547197242235305472977104725467222235189667769307848135748388329499514715081956350578578691750197698203334761874118443102443840725371457923689759874218, -15719223210916974551907191029732161739046824171823805870867343691302058805307479425938456429311068596773948576353217187709744343793325763858415502277364545366599133612406569009465739290307393218350638256334370549525188735186416622050240805962627075476173119800941125593150674142059107533392564625920073495875223109511219459319982018441115817978550097508315089037354626176223013589345230103875120607916853293187130, 3949937263541991725302271127616382053306627596424884855140396136874120145886086719548069967417089630693756824592494262633895165681996570497942184091408055965476637539792874555908104949996474518940507334731948555048469991993451781560679521468887563804042064320227330612104460965418642992149458540801221288008359084650871268782550648275831485716213647525298798614013964383960673089047600168792276597028849372720736, 15175578139343586113732975804056751379930647398593151727227782305064648543694657633137510854113430469548398071051947472776969402746066005838054398198500592853700386351837293525363004891064742834366741014189699574454331409295118170453427677181723651839300716214439698113012648999193000887553249799198546042345405274330279772477936254962016347150226608187458391305077721714974970443442005766519215874093610875210128, -40047756645880929597965975783043825169306783579673328060642682613293727756756145918465579101993556321817458540770483631896603695525457648469207473623164591931673775224133180307742276031332399586856876976818377592655206581534980651138468620593961104790098506257082959421385928694527219434101566664492274257925952796883557075419695527889785660620459086696773998501765217482695369254780593258388274709770471776326040, 67091122715572108126497627635006184187317312307810923357658884127232009496393906108804819003848133192460619707371977669431758685451782145967085586053235853255070839856733143287702178494245865445381577220234078515353481399149419079511738381455116263096329358994604067728237481102772066367164879455180716630514286888682071309028050426997488700785077374000905599588769658521726902403582982611387825318233040016389441, -92341622500362264171565178992013795904120993658715313633815245027930553373788429364555307391440363430375467898278827094520675413088276891941264137944533937204426945251208026180715312030998663383734393489232407092020286898880822694355656105459371120837672825562724920203794276044398136235391023736286106214843989106704137787257988753890073495207958706250855070338597941533742695353266613068442267817258750657743240, 114387879882106755243487314492704717665816846486683981162221050732240952104213010775565594130257825358238665067018557324118728922697464255266526422077498785088036093249453555012863258276445960282791167717595797257198665502766916899763058149382908431607431350728525114147345858011020065634414590752829775141699150560456075460883925646630578664526845415912772522486038525422542493721398791952331219602019896616010893, -137476746691947203448268980025552057195066819963143181923586955182611483110227508475658401973241794470080372862482047816998208460469774218325364151812160438689155074758059852736483126356804595619829879623458642453306780060613021804152297839610300778119021551460690675657568531727601780145435901517414865253651924537971886865898273461636396919263323367668555547818083657306474015838141997642984934824804526193903546, 172619353223028231311637434630688507617964588254681657415801390433831697690906491958913575294906964342044516750539775777992222387406655022687599365570338310200937167755281220288797032978384377298776022092422038622769272603028892243904833154663068096810756911609064946889062494497463535621918853657176691885973353831508982056820045545877304163556622402135712596130718057251984507245950209213173973709180206477463281, -234636562284770475336997987328821091246662610716535268631766754582395279375582874445916920114123637202360893419102075347241471244177274151861555365436174216580620348949237295735457449323412626300538618039358963150926661198971416754698257675120156280959693105797522925186280563250052067673050569266135952605950301212156403038769633743131049326268688757519697493437701365228581719358480546044393389062475655146414844, 334932126517656348918811128144214782936453268289788491157206653907455058300855690400695092747508455727387978269140799644751745695189646286027179751460287343649963702105961085511229289165117375349177420489373132201903386072183988501621748645909546133876701789090695560217836037753664859134396924764892169010609958798596328223619892518763995373337533130510500832614477397976005459403540714304367104569350376431775350, -473018281235044874623458591093804975919892938072713204669896954402923071652084582914129811324941966762352315097641193265578762300391920740944104038488033174480414172405440374806263532089863391459645896439677691905857356299779592715838481744040512906732332990458556141485869805820372048037783319207765417945843540485818817700050339993051114958700082230529657202095424942774174989766625484409101693091767880687558338, 632622981611106627419551733260579986437025975223929291031997843077576107770267400353501743850742055911896499510703381856049377763069433810323416016677020156732676774814219077262354228339967048265502135318219887637548717646448664861516532705447639886480898491861605262329905929015456983497005296353492758539050948849331776670281879880865024872698955179565246520044093997867635833086804324421425271062394691657687238, -787923454057902341433628767254916191473274007920603675060232567621881895653209500193089461918299079125090722055246889014267052988428810408776407277830358231238202475903397488999384183227494286373102975725858261388550422065224036855343086757235258065364108306515665524545905403054691967626283441222010453046688889578640567696377088671215731005487244571726234969289105421767960454705866083551695041804692841302261728, 920372991928706191398167201910543786452382132146607911103913606796955416671352898808492248062476468397223658639091452827971100641095204186836664358208911346416407598691789262646038727674391161636735579885440181610540204170965566036291091373990613938409282309817075757237540881101827132135716323303716841156812102341441034538942012319436233456235092137883632205512160207421396916968681209134326415847046563258915213, -1038037820385544528621049865649235657589800712679626326923031046881686462480207209681032305888658493547369858308585148001579801954702014746182524275763880640382044710724760224699518880552861344969045190994069362303000953212750194833672751397653077335834295243605250106635403735142377568249731447404502367183109379685352355172011354087127296720018905012625766835433469956455757919701557642068141566451068270762281700, 1182341527700815503699877709066213318876974381626463413174575495289764385148222612083497722758529754988830234675863552131612837657095310646322606056695992819760719623744014544888597742682655115792148206231986343652795376314525598531698592090167493452403808621075238356317137837776146082225744485977120693990070149210934478693911522694195284082523761114061321216222066091276120173723967888786518052795401371321918259, -1408163066484900217231874210792598938310506035087467049641217649205836085509043968752823902251509067383142076969771212313599851503354692786234009412162538996389784119646560219859862839723906799850185492823582041894164264412430722157902347675650544124841110888491983023012652412849603108172926589100964854331694696591482170231477178081718235610463260260965183218142757038755549284314764376629955239404295064723447056, 1735829375441509609034315392643645040770535748851468094870501756361481502685868905504403278063726235851096219394024409680159514050849676249324040072421238482314988171394888199390532948439674360799127973472636785892623804357643974494275161514532720614363399216534059385928362642303280709015304746245994489423515851521974604362012058855940349095883111504878695012437411957825197940094414758812398803082607423047159680, -2093761827761856377750653581748954601214356563437437956932877289961882431865259373834529889260448449813475409316278593179661821693609236308387059474591268363983149827128005256970331639538023582665206850259996466290494146670521373483978042214443076721532501950881371429140897712099539299204771601878092386500181754913795980131790587604885342406895565706571888689949311649049475302455882603807151722897430365662329146, 2286715925545490279822606002322292743128538205270896022797179711896999939457397959744730594811658017234820647043342284033598566689469999378825937357484111902079507625905869954984134050273444522629326113722219121145536541211208809334550664611827670224555675831633785828088675507769779689327819116155834523368824498707473442963785746119354618454232248529006012142478980161630600398083994219107832570210947549030054660, -2023007808434240194734841315117106631922787732135695269208513012500680110310558669538166025223311617446144153593724897835759152491341783604739789968302764000423853570550902656966937426704107362243091923748697380112782628253970535124651266643422659230413901751592693917999544158878203641958136315781765234799436426402870336559558531554853044510179801496056652160783624158309941480704216653807952382568289851716789568, 1008752344259001902849985178924102282881646802939190650265303786823721498319165199862428724960227495203485834370572109426835151039844389898958002672678728928728293348078012498194653999018690894609840049552416510036474517729547033311511151227777760633093098043041220452460905924828057341622693208533551235663122793035301284910002970216722376261076999840499247042705931609387059767474557706779935919835472293417698880, 923167262542267571332902960034202454136682908270233279540407156409111459259929622218844859908484881152282865537041290253017247534748011294402496426723380750167146365811611493978201593202255971079418440992460475728091698833987378927753195108185053491601483993419007164600819084112371530018401398526882492665528526611398330420839949389480777747738994153018354930834413820370110911781313136620647367682589585919067514, -3714395581299932587939761101551537472392771901713259842835819545015199571856875032412722572788320134089427836772327753557431477737859209441433396402787593209405637624760292410465471699422216333010669262912870775426166780950242349528498602871658833493345037910966210021878675238336252044399358300684841441170748640075121423654175408765836236382311607025484295086142827318344233721429471036104378234439234790614228013, 7078489064318735345906700313204790473884982424473105234327889718970897648873586904509244564559131590357937449678393665349444437135766587502068596315398885620519841431054294519132326833891200507189484182645923552914583332746736210901397901828156051942215198343389375097039198425645539359909269311861908651033321842795769671995585891497271670036754326494368892811341115705295377557279209415898426404460561931670821100, -10619625540301422236496646270158218233012404383533351931627806174416582652856794275401747205317627644705858336518618691676624049236464797577398474717816621387449803315094705059160351566336086602763992586084068760639807900097654407179232698001430987306498907902358841094219038874031057147385978129068060240339483980026564077716262033974395791219787029343114866595624814053529082434014163554212698971984922426065967905, 14031509626190678245313735560732163075404533172153969555079286816734936412725185250012416794842876380393398907462600461392413808150069088887774351297807180613247659033903645693332997865772614425953281522563322291741860277393796367512108395267993527818358241038309951649252650848252856049330678659512462870597328819876497925218106101066955405317844154652708826367262213518299728284360078244941397805648528376025022462, -17279176004718653909842636614693057940533570925242172165839456379703054658641119007801063055704541788590930890478611623175162966933670132551866918039214710055837967839247433571562084238725827411457874858893074847403299879723291826719493377457617314763264324457590005529613213159494354007182511639689673050479572035225949213756513231890687280508595302696397730029777417085261614124556688767521484907475634394849143240, 20657027338422658952212691217431989770415728174701259829172779055843235264135679758167606421092700196208596499828136745293368101099169905758277903279847021832601008731139917183905778437910917747068938847903755017403754023299702388247885519824080604596675423731453460846724535665661138274313910688738560790605484488009650300586153014712978168846345550189709118427683338788450916988925742514348969009415105250802374848, -24667468517063256880407551118708197165402815492678005942951166540180221269871424067186951567916609281734227776619774183532327858564752154864492634588453357508887009574031683866484919711674302976027409883723967581616712141365351939497775652037716788181104081561019365427439082323363791642082642447455360328759100510709923094450403593650304126736773249808872109392479535837209860303857289302322059485246265488486540975, 29754503115498064748934275544337478509617690769389975671349770052624495175942403765037792870523321320819232703339307001732555362852788917647871892448421258316077139315821151446647501333753033074743108927665019160046966030423265449892367631563889217957756411803464599016404396604583701662642097653015411087159346241754511535834384361836702576888199165743153289449549541589663290418586179998040064671190496225450196280, -36008468533248593880921263945970717295482539645896202656298884556733667479957534328923673393717286227539645600088700724627263438296184907228809145914467465502231854531791706385564057847029518080320830446756966200811939438679150948343263421754372017909440430131217218382386014340494135779377928614687830186235897062602081357604092205734283173046139374651264974334526217510013053850779718405512482747428645969813702098, 42985242952099894279589570328410010570480818105565626862292953217645902432416621485196740114985424822638421732821924705893721539163800467924505342237253270876134463609148778645618902936128942962412047943020373381186859447181362597651813750525912124169228753880543382721701573217829934151419326914242929956567194834242743732179654139918443720458461144558329225161289138259198415745097615986728715427889821319014890772, -49737790465822845083079191456207956103679937184126871957263138696075936564514262519327783143967224584790957797361042695404924959894631937447085870056159053539974022966493120937113587141043429576624325642312122785139376479199972820583594800024159569492062613514746016701570237221044940975431368506330157485575051085237554162650623374210173941053855294460652583678962386626583121137326606770418221318427395112583517454, 55061765604933911085817891806798453743464254530838696961428974263377462127706339731230619714422455573904509727373452495000199863819582956567213182355550759509355111406814211117093645897935761711814019695026741323177773810749812233870929590581098695550692769264128785725952583201610619618457839422143979078568523941689434099576144040045555548929589876806653619059025318747442470506370661757559848001956688917086194130, -57859557843577211658350871347658215197101111733362510749428306124473080515473650045621576669324886428454449936056751395260321654962070845077264094599784947277986846977136269409446036374158235961188012610301431418074968166256871974373770241168855795936825745970681926906123113547108547887015652808920633860645750132518646678465939886902199239636077306190945964685461096091992455134020773195372277306670298572496311355, 57477312409007475541966747037087563134648404646953453921018318421311684962328049527256742437428349875839010083166639935290662706222583879451782336773490345743965440788900476855285618437440248331703739616228239948648122925350220887803132394989436886873705498065989682288520499881949576018204747736915011110646309181653043276515600037632646609544580365841793234017042719543222003835996735000780657044082431731373138568, -53888445080068734327781340670760462259630879893851318671766348931847766529928694982504357044457106673784836374400461802377785305527475736677007773703404029451137385665332974465167632210911978355799665160201043881806294232920672441012513037586792279959864396771270426862750016463444320972499307627807408878955565838470730500390565257188434661677295357455605560023411878101633683095462332309495599928406903954890380177, 47669771186195178034774466575686897549362631490958603588532983622614367847117903891739668698135007352032423969264064759984700305854542675718858225942159311294116825849973996036412556692196268228672876026861081433871112715252180954173042868458677817917127149589486704842609865380816072046804333100861765881240890022206489207184358186359905236463909777813510352820876902681053291472088920976470935566799272839804273418, -39802816163879305039292931049407787067725926512622845824557155037603573206096256315017777991511844384314089976112193351489867442408753151075738022998078530411851895182497612197480511351576951826452929216712325080408972742143296466342174886073523132875830924999476928862990259051344553090125287034755434634616459760762927413136732165293670893413314294063180247038060469473309658861052110823756137593727011094003840075, 31392549697868369051344105003788938581021100972704747836034574236108906512279364114271491100704185733751627668409559548950459296558747170441598146032733829305187407864390673125946666484111554367634152763533367061988211037852693926749900563388885281132576953904920627285538598144787530694005794501277129130465115740048993260761903268642749731039075203193530887933913709181398463386865274891250745278793448243970958164, -23407688310418911463139595504483739531827675876001944081707770092306593991107388375600911029577572846637043696252326898640025861836274822682574232078799736504432299835478896424112115018448499791186950811082568391824122924309705462405787929167571314315900030196069226273084405846894320388788257456850684401720522323811502370356670729426735514462829328016490657930377660729376977161395057511408574348018026805886400846, 16515933847343417429328447774575843752605374533130264733073446708762113491289307613744614499484634116153910925814193339398173710768802271522800209256005338300009018158897802365726970784226353374716695486413153314022269331063277582268872951502556236048832782700168630852712062813219664596416264347249406110568189616644282222182980136665578540488043616639239014121193266245929915409488785768393594617961109956222056702, -11037010376869649913322210330424701828339323607565173375962379081232919379233139231997336124154484410886966639350426853265752862014782459967482224972988661369652121779900673998915428091601878806425338603210435148949816740259342959917017507168988837292195875018696128406721742977500057756051172424827928001815318073035938383553064596110611046683686148558725496360824343264109585424352822740516670097488389693431895591, 6991707918209928022021973989824231634055582840652239776648811623515128650919557201654332160464117924680679278818992742167157466583879222897774157157303910600619708475867020987367981363129584465028411655516593360580280328271792626662154350594628790581242663006109885708636699132931755073273963981899151676336690990822045899886837538852037055610557923073874326116106218178653978706771420826758272683901436842129024960, -4202039343852255487451657353862686734769210650650212660660325275406593542703456884242866847656892142115517965585846043286880326053584655364787452730564501218207536526016455387799408644009412722341051298786460242965837918542932952394584242826575792337453528148023683715237696707618063583699074847234718599651200529794307237287039543373351961553903462603376756601967166351695892553395006018504308643267366479803741232, 2397803310113518373289340791084386091524548106182007860754257429331293399000784092057259968371742284260427142546840141686758427218217658807562597622668534043361312020965400964173348074315778766045089647483942073892826604607206988013666775194253313185087620827557541755790649206822151007805236818493068472940390660096833805354843945308041095076987642062659087697721385404781970884339518550182264657299616101099883548, -1299943569263114997166886183863500944643755382820442967952345655481334269585306145637164878650301437862200159576490744018338779059932454510934086085918246522499866407676479923050653639122662988235787441789960496153816459097303755532181086927908144944652534064128675818858471109681439889497633119111394511098170312046436412288955934381086601005470761221811840248985420385956783169697187038916298274644244931332145071, 669869595245966563007502577505816276000852685681500515368177815923963324803888411040885786909008379768405388052969429959967360135948317970143131721443117737511719589235400198732425793232703758078244150366350903746945382161801197705739644636210434938465183875555831419916260534072278987383953036738318417495831083328111366348667098903672147058850774264261811366133492494223689488969358319750731133850322744718532456, -328155112591422958705706350796297276133214706119717756483675857746637861379192647373978202457263312077959941995797817423096600068858300256309067571371225238741039460989035049321957910482336096948712359942299091733271018710755872561428082262183860106718230546127781694332015811506630120735048401778398861892917743531353271900539908112299160291729929240650187650187191482615681114092360571767249985984441778696380365, 152783199124357376547952324880493399060313408364724293738237275941385551944842634150169767097277015392224484711394045059335500179752105779946901225617489403865903617774132726196792089568271585272575039659661626256488851683964480391985128333178045714338389399123493505725150076099094339005540564859138539943111110434584079688420245528012606323036416540739228665817656786195399693934633913590922540341713397166408930, -67549503324101019177424057662017970145510674740450800089704974172269784378440837272165251563740272809357490907593041021590419725309072775062652696201287363531484833549216466006046159679789013641968473861385208742758992294766249779092346208231434133659189493632103070501799397471980784399792606470744650079782147135017748756698676348547151104554057043299307470853057031289579227139818213151359675053751472361693924, 28318376836145824528988504719542725994721543421241972713140194241438324401131719436301260475483869583943000229808128233905182802056584755868178293121714214178568484283430850038033286170856222235847739216724661874012864173633541697289120383984567111145464167861240083196231013331261792910178728981256111884369207247055517491981277068255377870536516564019326167772094352272393085831600830864377596747375163055555920, -11231425860887820330314461197889305807720325089507424997529219812689634091129449918548282215728266261647754501129619867034444959670518037766670511413819260095165521840478667927134584643241716534482249021121795400233320706720325430232099894575475280042977132893648152811508692807451036924774253711845879515826317220834739747333792799698960065629397833560465725193863450777244109844773504040760459494662683386643949, 4201453412864247499605314662858305961684181003436469200816237920624504100274965124365211404601780441718140346188865046131426442226878574966179464769912632475718550348478535100272925885157099712013008990069576663759723490730262358398514354354832799732990018432431604506854549343959937901449781676248420832651225680967437468293864504933410124783726921771888696983896508552449621541787319603127114440927284611194710, -1476741597405146291862540126154724578176234189059823716584049933307350224206231699836886002859565500898881582938306474730275348522354883583396360784748880584468519430261896135200957214500010010593961929733396102982261339862654265259408692036286931299946516443178185446649540669635041401851425949517133275820623459828558441954171009417396395372764094374685357918521402437111638320963370218908411184792816577258559, 485488371598977185283847356736267249069635320994856902206454506668286801499691734038804733228782337471803343316852302040492459371404253294684391241800596510060806048266548939703168316948495051912214873006904433185566897342367715358925063293298259096447396740841079073447015798823422715349751209349103804784017122603974731723703347910909625232553034065843076554057413313371092927753891842905494130458842647648756, -148513411574676528459495298510299494091990959383547850761875029342675337861180671482160359592643827124093737363954424117167311475623033382287684525335029689355417137312444783915218527071761991128402323706574670295090747042424672946330020109138544254399139971537076014241303413986465140674184153013864584790282565451979439105417946950915080483309837894136458469090205916034694065972405062741177562443620344360810, 42028385174561047110948471922941459452229339492231427167395604925201536959874967805165333925739223220373314004713908807846070545396775550226066250669664567790221651385233756584133503839081259538307326347051441818324460370006894040499050506192042111608612548385487014551518297329451137997218123483371491788203788696191843195197930482058337177507256345196358219705402552889835754086117790304941441653842699089376, -10932661724460337872476452933379043017353238313521246302063653045950430765402983736654953784198780608230451950736806365270230571840722556559425944627130704472591350654360986192598694113078104789136702894565359550053561714519749337094048770017368715216223166170075367076604442898914179398450050087445028596798461606735313881874242023018746744011170405635953262901680094557618438781653218319023356481282246277420, 2595669785504680878499893489584468946842941356408391770478218623415715107986036192012472512266173353326479781496815090736162590868344077311429822149227947962102657612386368905539394265793090668409436269028513253734118342528586957143299942189050921505778984174978294161811059889392633742049358350307552652618335749175270093978992097409959252663829217940772857706822706683409607060828256040331551520103367388416, -558104935015574054415497446684320055903535491393709816267022029738020161662872916458734780964818876896661631396824027234099375340782887696242835967620823858638811271696188432703211708790561956653901878844578660211656610362898585642437881920127624437104534024551048530933726661503051709773025636150525930357526710561589307300066297070140793841559089943344853145681350669428369991457178769679675040012321434402, 107723623760218666862836296322053019400272667152748663612860861768204604510175534795280217355054328533399110581193982262307288223256248549117670319022843293070098254828955418551010044950325157037356612198048106808972910979686591134443727946708747167846796117375783287155991212059577405023348449042240774266595603167438463464052498531393264648609790483061448270420433312505099177128182690777243841711922498288, -18478807523695731805838706074571699776052425080235209564892228520880999822136914600111213215589470554507716919898863508610935355564415351798210592114242325023018512230935884374472366931597303462302324277382741618313804378318665644294307992126567726800568497097332499998517610465162158219004783101983758544592009496969956468502942634431213725883400620470529878313031209884888844568493601653428011472385539338, 2784240631142328175607690899216824299427574939482483291851657966804818073675131961021247937794780669703546950751210680846696491564330656102388221579537779474925989501003242127090784328900775199663400821683069071638421588035615403519184656977933011247215986950175069329855409999481410641673104119408598971148043021404326751392909601038982352319253721128628170667591913331337852355629514448111283988841416100, -363322359255597257922576485134206871131800406950152549289638775761235150314780830099919403858828872175936221138094515322544787656129297713238335603946587302349918917015554875340074013225577801767517824350997597805515188760930592197577543792020293091129466114176776647626954260944028463385225890214078354405487485367348540623891405600427499499167742970435705148460193591084893483422921041417813237789343076, 40351836172931247374719709292832467005440825484998976080026698143661131380139943241126350064687465020104725847247797184403010575125339171490048357019627418766941580507054378707111166970739949683564673504094594469833489952345371080281717343281248765933475929741289757838385728897405527241916361555833030512338631810552592718796328089890215037824544164902020520518650492377582221972675986563930305931505640, -3730043715200569907483808163039908201110020039207189062861578261672374089394386254639037112649027112815704280013551187067379243542959498972539739616341525401244652253117209652639644968680354359469400928179860085111999411032115300415469171955184229095639147086853349858776420856909001568320777249001864127356937788701288698428120024833265561994085674206487164411267525709047301227393618740952768440504913, 278490966138094246910761871008509759737052426559838152574609004274728728643621401589931209772558726226536304634086123872234399383368708076243565063402231533510309646365700570317576745855372276202148696407315312875709007805961771760520974095389144234503771158526913435921353275510521726282022066350695202459950680600777039731126491249227590246892634579015570220430688556396908620818245108859017139367840, -16089937564836314021827089599287368793592291177946233447357478385643065433229987602590253021515791382742345554256059873685473646066379038506687543412409366298284870394983292643003305265707799973566735000998016540780640577251589745980766410116931399181500183948538414722226192969368765169737951568416176036020969002986889365221580280757084294549583318134687765127151792921131640478410914591201209206875, 672883703692407774655017367156883579925166222937575662864053786639829103580089626996781336954232486426674045123819319741705591418744640238262404062733637414397089669634722143920190563875385470861392829148189640704522506605047253344948829163177540848958388544727719988381140826236016466513038847678158999615446172913766121871747923278298280069673888448982129276164997571915010921022287159963275687500, -18059570166057145494838902953755943271787887569815944885614714489307405193957874592722548808012702688011377454392383003497389678093249158101998157816947256064331588377021580949015590962960023634399172783043432065692044950024009849558453147307243654322301896707719452579376589320791515461989979593353455398029986272587048893661416811081296570163609004194038129795518693478852058349203950125117157500, 232625627401774720637277306950258773789814704245589883214750382758536022973413059000276938210397058873178914149994422585469846174732251169456170227465598688696075401580663925017895874283824990075262957670843784687265550972007542487900636070527672749401812630253024802501719487230380686787447802900728521542352564728913574719782012656218386696899995119183225430729782630001989638089697416361100000]], [ [[107, [-4941248109152568205985193719121698128889201549648790176436468225587504756375504835021650107218836812891550253158736717947929183614260110073603544351461842396598608710045220898810807168593772628645798516876488795787099141161594199084175809082392284889537518994065925703182597802822114009484144892415855104002998398191056774550528121611441075862296876398043267752926521511200270202478123970831842304, 135159549978852459667493267440075501068847654915987058368249541352644323028413182407566124792330497303413698738467096552984381466939179841631585774175808691870875931530150348395032265486606137860126045691877875116106442758913986071903192175136339232744472784958662259547261004977588133005547662714910179998363889520754081146422790870975669854655477033031198166583674681701303748660998973839061619840, -2044229865944831094243865472329006893219209688666355748022042645484173052009144289521041818569717624578016993977061871814787490304649566586266115851835035389875073491503075889014904813009209199280390149716323639985367194859663494088851736726756229768223910960267582536285809875175623182385281225720814392156152103784843782658546674670785485289730965920308351730913409693441955241171565849158123366848, 21900096596533486808126798295363223784508235353045200209642586908674904747141561009759006579405817224341434954288569233250375519222930765696921485042130484648617421813620649167572961959009618868190293093369431019795775705843347175231824914244968812302400319016553353284014165414898708606564529227050357298944318153256199544015841943335335106911231108560667160441333338629264260003337867384480688138112, -184386301093658653561502627563373736360953443849723629400943723336545814668383009872222869236866720420283364025861517487591622768374463809956710002097531166677983361090946048590773927020223804067307591480708453062406257713574024296544631233483123754855688280470601432462519143740204550049753605702868298315292485427306576856505862221449311934062168618038684578770694798578671518929375700242474842672672, 1288683169837730204848625931059890796823361407131944648289752837814412031588207001989410468747514258898701906751614816204706337343256654122262303485191093854775915324010773323787178051559689438555371539883325027980309113446211398009463580910463868948727299841818350125016162462727083709133202858266556716778921343579399780026677611409842985938265740991799907875470865147222504787024688736408687984338648, -7732402666719165540038644448813347039433618044000010923401556837114401194077566307418735388596748407845857001857557610296961790982653218502110283981818390903610305531412751169770955181152213625545817809724503991876529510206802364905877078793617033759529922922423962185195566561797812646172192892894660452180979095302046216820554145851377081973121894762528170370723958363409927244442297945796538183294084, 40735012421723410221759311437668844463253357935195765013838748304645208758653637317353899520937123422568415621495809277128743127953135219980963259630555564446922544484832967881178915614603021313585549751756019324877611814498395482328741653687664452976363666436120125290283698578143969963335244383714042364094913451446800326239002409780411991920120348911986757673412417422562016930674683326761283938371156, -191429059428784432283598960656894163052020854660025369911730495265366607639273570595957053007917125683951474325284475594824805857760189021639529577405217619164729372310816355393044301345706815556345318408713802374762427039680686715632883033228090680640558942356685059421992532816442321734491629922979163591229902609390619283386311527537201795250105580643248046065886822800868483982420731479647790414134332, 811970101580452692840715345427810176552782811028399978052645988655614710420749159187933516562951326235897346298983602447995954015005245278981924335486890925006484642572426410533702540463643841935406207241607439570664160823481271804862674826118532388902593911612990076638891090490377002589564697497832719335580464684442358249825275715501997107143292771175779132486846855776449778057322254434322709719414802, -3136591947174468361240766449677655280739393207807344114811956762674221033225184562025718555676708356298917163392766088341089768640524427564745613220416908877612007499624785996883968115476250242138090715023162139115513614570437822446465718009003380777728884343710742822639833483831491569381359308972560981088279680923255935327451289808502698331986680914286106098804863963951228556153329834152248275236855027, 11112237886245506080433131590114961812542480545101753769991919788367320211178012680264756952666598755602822130742368016797399329722256301613156145755382375234915359093780920636261854118397386773814882967164466256492519782088583080862807209060413858406337120827446197065120465456392954898174897273414081401072938582244787840739177393523626719871078716971728554870700208509552272264366471185669731347514574591, -36306510772715991113633097375149026889513729533751888271711275852622307692633758939546618636687387074171379240513112658293541826454624958014223213602433056312300596772197261330700388252448693100346419084420504092037476309439364201268192582761196476163795906686645331883570421418566369008484367547657191484486023247570400354825596258135042302963020503566298265574443741789106272780400528911652414302742083010, 109886983718679177183621387561141408656618782297471442643627700445926041544930221860363860334670539226423633513131681271085772365154826708357103896186685101188672898920176923422752522616276458684950516477452505667285727423959099997302867604049300940901010864833701326991563817361232070553488039581655254666237573356596216431677052904357863074105641183718200002614247842180806385274255057996952998238472176136, -309213028712352090351102212174466827464886439645514852675412142465775215292676451003679822925397336882033686273524820710136759942226818912341606093397882320249974930777157284065910537524493762189828801924198822488107733608988494134182254558660866517079032488564902283003182495389490281583028731593534459769370586823091481489383371580832420082248462421033924509885351587694563436367677205750510973617048655466, 811351518464495882401149110625037453558868598876994963423357847572911273765642581111227305139991335456110478566155269252032274721350966624404516600725470586052846392831251089748183254473081120090669690416225695268642242175406164346652492509359718979390804934469052244590801959583615648231735846551260168271874709286829986592739614786011183463731799047303307246801002051042868724417814332075554266633938420232, -1990213029818135031206292028992860343014810007107112544124221033994716658637664666338183630577915309537922482867234707784177523293075052901493324275605340467348038524059491210982136021475416075825456961294068015438810028875726494362539116835119624410843206877001630255040568089024621609052539390373938331236358871674551854239411830581079786067260630239055383570386764813986889479850263893970318085421968553128, 4574632889760696673769879685668650957728539996962660177447243503030158813526033904636602011425186906662234436127030699554583177457449951369396703017413968968366558226460773006191704728060204463544312190743181186147640553696701444053175900618045866025988787716320161022315568936540506249078225599976624527930852861571581105771199935806139967321720942392281356225842095002351015140778515761112204764524176553046, -9878934688213818617719818205211367904587884485500074526564485119072788647139977759953846314736774678153697168755098886366775103815960672459275772827640480873832173606192377143556257669797799022358478530237736866474459008761912171025586483896037115157921901595219784122218615812648289256646978890143267460814267371772970929257540338223094256250183739193096749711445494705464795309383161041032156715260992857332, 20112972695706273062069684180218698699747292316156548053271857147932756458019103748053802352144319565066623167268306976378570643903986094950374765513720435172181069069437699173943703732867323847861529579330728222039591574907232869623657502893169179736940386076702557833199454941023969403520498395884564971857099971598274170534067971553513546401263913844066435723303420644498573735303758153159930689699894736792, -38814182741930896960812408044663285605613309932931495211963932724267398448966132220849629500866487846032814640128259311740124290608989845512884413212323686130082894580198341039167654735618154781395688831934741375595585932548667068187229257994688304959146794337386724226356223456959906088587172104923324970850188955491274140100112748984970439730386526108620145509513859754169313454780860182908776548646691662776, 71618480203491528899346308114023091288726548634504360544721846227270704669092062489623029811531395845921574612726178949057571455830754240806939998736955878948263798765755063416192275129111448193651641583649540250071350639599180716886191233602277746730083498945159206783107567825053490889796869506639783682678974732168322032497905038037741208639270546247537486212098453163481955456658863878095795510747779689408, -128070122080153686661011277153530768010995588652924947688829794285550403055212127356772911817415928728053404771062799900391356650915974559086000844106675533195721243752041806145975358282610964745048898420412809927306484473413919709922292839899380231346951871872770656822816787070760541702114172600680109142206156901480735929414760099564905562624730377308565434491978703687318475384186269501644647468730639696057, 226138530471281977614115566743216199191940626241172802975481062826438644737121009122108451736805038476428056022481789810353174453974213899669750539077340656488517065101720447503364618119406859156879080764541257510929813559313514138925945517786822222245583308905108980346200573727188348508395885616998698086123316506089421790497963176279871393857892727020105818283028681055837564606455500163903675764462746878869, -402511013021192944632583566883902122514470403661306479898738900569486203637970808169237395753895832641292323080620965162674213035447527073992224667384038802627895282641284294235591668247203795067947275887678940763380360449928095653709479922544189613075188061120781593809886518558002327015111486327822177258415359988425742525068496005147095137584158809006232467307940767361904186147123865611538644425672801254225, 732834375198016888884202939245690245413116754702003067261563831295370573962383134975845860492413525598815984429254925857023769541090114560921665877358738950997141169284220381872230644015763545795062647866363376535048684794324544433955503403461953180975103429618561738959186104880645926568229977299697971452392095523350873899122714820954612445230175154314698438850341180789795884685297238692573974768531648247145, -1364942691549462865497301718507702064687215329298143962028396858683011207961403869561810758080985350813184256926731478391521007643714403712443039813984707032707298256973316414834840722001038941933515033711744133229012831045403363905743502950919576549508849663910446806682686992276439252555973849929540735056153308674387485052996292629656042776113807043351664167207060336844570323436047099825481721881740312485531, 2561473143136355973177362510458449548856135889894976563266339905769241289905738607592217883409621673912656906075166068098811183414932053612024737260002744148660195917667092390672776221437133952848846558201324719856855483672999725868385670596062342951419986395960659111401313419799340841664155994525969055519392854382602152884516485080185794600684715301529422946368336712504033219591261707773212238709063165996403, -4732824917685812167569525238456917000721343831987601975135656797196921156443648235021647103068113681806945498242821382362357522012703868880952867257119036952862073672737347380089856486374457012868604547015490492899873039859361301518019569417336439299471334932536985808248661524836239133189494146807353201349977297972596707791025046031068850670787068082456805098106907116002773682084238567924832347986500553218506, 8417355663506142870632832935156547199358337581320968144832099763615579780692446008958643438870862884005528146276630218584453156989364348016775995790282534043751996740858227106983155889655739496105366236625630809082579581377851508740564640227014709874353183610142557007031506895408489399249606580731687103603565650728316166499242376178559374323102562839834010480263696565061606940449312860066031284521854747125846, -14142335804853251969177820331846541859427590950902449037626976242634713696295678957017911485898415502870681603319454508654763325097141386538833706398015959061714947817678111936362701638885343208243160944100716894277407689205575118551211425475506946109682381427539383558024693449352515003853802834061508183439452663863747897020526895372929063371174892462092444771630856587129683911619566595206416638799098434139896, 22099409925081091093304955267705812049372161043487952077608256892369059424103629860221076920305644444891127258671647451950863409373073859793276084664837361687938514820890535421010724834696898258940304429384894733771182345740279373238014420883407388267409785119033820280863722880575924682412111311145198503237120230722974216637264677339512272749507162855269396633922974911746337678596069838202196032066532596475726, -31625445830314422961024886910733424078821771296219351276297462209083205798320181455653963337861028348026251257989602619347680562880699722368815007246119432935988514409855074804413758297805642621964740296246012940771494223579504224754828901291778995166242034870920294332069974841886381731649321270737525842219140122163137574320065979477654911612035564688252755057533832872653611784759006327780047962633390314535882, 40618700961366299925176066689028976122550517853099810716339855252687344872895753490922202863528288340765097912518200046768724108165274784817768365992230671372259905201448099893662188868431833003601621784825707679599595439030547460846542863158000229650446730555091441396116479729565603991715668646105560423273637859774962899205765411997669358400804371023927719451355414179600734479249546318175969529867984150472610, -45222631491150999296035770354744289011491849248885632088639314714181991170590528137968894870082676398812489071015133003188085711231338496093928336054642864522997375125083034662704935410357812067737689086450723741286745854671070433425974119246277815268835799464636001772531378925343914982568795062257399168183167297923989124096263497006280651345513633092526023582740848259578977271704943330666367746484934784540726, 40276771892419187005958667580028032795193276710964466099115923824368597684206786880005507448349300398259292175656953852185862543677396379891993874141622087427256097318101116004227958077933434584091148074203763850364806691932993900408602452615117432682240715671928951199026805806692323531156669132977966356808989331095590685355665551531375093750816340957961184481618883393297293615716364916289063507871507501312586, -20985807550094763136489058805834508828149097919123400284414219016711646097266420583347208318953012640955320253009912116201260761490570680151342173586380550604179867153417867077886717473969755313871171120881163337616027742891324994414691314149255614260519659448569087134924382021297925181715366238872620702392907718038326792069013418813579061438178417144992434505354060428699971474217680784658848846816178648879059, -14191127178549486144860386002108249237162005968346276816761791535153831227433577763245747686887654325063053420922319758322607462571128606504394402313001799710643916480262280221530025691797772103589773232828599621976214626658306805944604481250492727960513221525843203610170109876559831643430711580504169985092130485816202232484873168514182226756812495995024580512996729940696496923268956818395842545682221115683852, 60305585421263490306889299248872811885020171722615460789665483001475229745973692242467283873207938137455011499992418822106679311328922152711180809818649071836621567416911850470359507030505110453477020165813050893145752545861592199646806390518911641020344340318010344072412903258487534947462515144098138934787170881027287736123181075734749738281404756402945704122431474189945141310881446140472669824599002134399846, -104204186032130224496561581077744283061761488765362585868021306253577228840430127107945573601181229243452376763447250409365568512377579830563422796420351355391942182449279865143258674168837346548886023057383441811153770706421916830619950910526806222096732418586661453937129728827545619810574770931526223691624060505134189426288094489101303073892597141112964990635848968842876822988592089049050478618455678299172474, 126602678726453053905324980358451708397470935036974923272329715498547209026213939670598644636087057509067456036200668721746694274177532898993235731242286592997606198740857501043872296809059028778286666108126877389160209347861625368384017680023684401296003079294596166228284021916633999395515128243368788891552261574410394020364364893284105975727933871127886959164971023232481432559392825857743147746469556099454934, -109228462002944556726119829702367854563829285098315761873744285211791705247957342415056180394196065365018006696039814405919982949481076030221211950934531419320250030494090782145158842475728034412921233240322917204286781143527658473023968184895298590127902986407834216636391218365070702577732980866357936907466256736414608962545118590677997551032635543079814751338154642399558685718416767288684662557314124159947677, 45599620248604403187514702978272608829302214953717619401486231705416909868737769081807868727297012931603151557888331276110076726905930803946083297685739218687069920884941665860019040224819743943289652307563914807572793595115101178813335563031816519447544708567696993670324489907332101427057867288161040131299173942330506989091720058843706180194992877675321268210391647489860557888661122373969315625021593521836296, 49585488436438611964264173768866597504104090504519090031493559345732098423918291495555986615828766778091452199040192455143806418939748195775195063814143200487361395307666252296446361116226430284024073082498531256685273846513882688426234072119010168751239330857668829141029265433300747838788320556511659433735270778783222407468399186645830915285482791849047534827157291063056706216362241768772296014707802512745594, -139790203493782867692693275837915514205358192257798470150370306658932110688146664746444467162407922541811602037320205311500078356402052971077730387278519947695658812479370631857694194319624406654234629314488322403804831134867633390050756038228014755400793998304415020910556682259237363238155364893843359864347657558072176377662772219153675006030009903606671375899508946363988747365480169063278437144372971326391399, 180460017753431277617162189320872293926854562485675051351155383112861545571506856082331740851987747981355006812898271432301224213759226814115910104600607513821806991702037190750673779807968348711949917685367227551013008803495763577933517149222118135050034347027698954392432596065288820707491849359214176467544259022173515282090086060530906617892450591066663662839788603080688850351239304565661816137808142041962276, -146297695244711536978259208108013252100945322230785274860838498582350478040989245515787724426031175365636450391671797473276745756582986415890032123753029799306660942448405403846188495622249814668165907322835358840435366292821112478378398002134524470449829250914286354516036098956544995828792902177749523574269320925330438048204011271296367645808793716594575678081282283885168267677282024995491908680483365983526663, 61011650207299142888435283589288093997204825414219629321291413108097860661411422573684928384352981541439994785176534602137017421699010943445201778546489452156414377177929843318145527239689258524998439815315598779710239908260572221801186028697422642324249130078743454959889414209929376294400456398987508236755161190068631544364545446042720514033406552061490784744412404641162663346367361078658203916018879101742740, -10994066612668863653781739634666530309825761081819345580525323524812663569633602782098653756647015680527282074636127801177163125743266900647971480001034922572015294580609837256338357991114037418729738211083011467646929938241326837639191967496321682467534411514734852842107876061373316347801719688619624627115325680070912214463022182630966458748773948148923826619930296877184052527795829486318316057034450084161252, 126005488214343675872760856926234068162689297075891285964998375169108124626472812898721874224511420774473038802777975393758496657829886137995365581403913006500790886058881963015558212028048794831430134372563826979976762835167242205090393896922341808788253260986568365793618267638812011960245320629596687511047590310710977835309591811072806911658980759590375187306823578299612062457686066340221149406386082983864946, -524111702560155324947363637908953419499461974243557015231337146590382913192169132238669916111109694719868230761952863034891595053055027602839303656448279881370091093536453029437438916168071710704763740466136110675512634677730883334682935838229883021371856412236606039867241336289980566625217344907708197971500893511021078689085978738735410011318469559935520301980920119592243696731700709171653846307663400755430209, 1240559270437861410982796409086460266811266061059518736943938270471534221921722910834424600429672879224545444493387488562165684788206037241807768375527301220907843165041974941079490207121188058688787832773067784669256646493894430166167426273364153307319843198584150452381547495096432024365884414451457611221225917684146248510602352194646584181735392642007985185353822563158157020378973951024471469004478075191712408, -2178827552069337365366969800043632921507105690685669455414335490243860072721593219882358508754803742602913447630969835194678718049191050821524083416222173481843288490711527862448900491088545169156565567482504123385454250256408193401790210671484670187493558942981876884841192997907076669706262397065441909350714498775751623821886147170400569812168454617089520067726597815082117280157346603568017002794019713608312805, 3122398489876873039629412072436264130427132979921619462703057549746655087999567109106509703334996376849685070226357435121454553391808191714708536463298741158391354045625488083380519832020345079290646807979207100512759995072231453203875579290283719778321259157640479718007259317836790926976934883414231101639545336388506610583589925981738491546203425322561005565651095569604489789873053612197153810782091525866911683, -3820877044295516124640890135820618582177355916837139631710953275931269430357100583975923140465471369724622310230022000051218871818351194913307128632819966029613531485659569404494098751630502425778385735647193387400390607957501050687872329746542426037168609417731554773608655872990322275139561201458655827887617465858745937937127019779911469602278813353143433993520699901148466187332943669795175089598677554199168441, 4122031925193532377875806418272346082373753513635972799899136066417239261232072622987807104040215641039053295310392521007561895921083178313957483814479393547680247143967974871061199382292394739751148590721136412826826597685801022679045527177429939150004368385076246921308903079921835628101077429210393203911083840324847045462530118040146654600741280221249440888398783820698187641440236949336059345353230664272301453, -4084422270306173452831065140259565956740252921146816926027251663289899928643240665226564991754573441348709451099675434933738726778297140472240826899728026030083003342040190070162730282392204028827468947688506364302599688100441507669186664743263221672797519184600381713569631948598978128173404336338712434441179148810661436019754174796857105713068376572800002954181922455851334138365465704021600243744764047116740737, 3998882398200229088064411578930079031795311574945126800776755060998104642260847326427432177049517505715735362787507217186042908921665885598041864506092429922505846911760080386722500444788983357991581382578956696987417522970347468598202086523173274816208773047279275438966926765612417756736403978434466537832491153265840867201085022237684719703596701320265481004809861662838062192869616705313497725090005257674108794, -4283170187581477993490552951816977497474637643767082569728184885907610365189664275033048370599812318868423788512540834857356794689926092406836916585851354704911572321405321090162001383205972985600940507920208080504108595681864073559081913146626590241225781559117555848680749506720266814663888483753162418708586696469319192779657231395959727360347857597782407904148592246205341396023163407430817810105379106815145769, 5279789788553972967571751030983068895409159249255182427206600245410824113714242187250820349207747634813484856039172919612784616683969613856115432294054279377007891054382338072141028396264703799479651164270557210039524320663526015775138596021201549236425153706893836281577946440415106236025676420729708585976977943439142688439489191352599080282762071393872798452817082308055566882220421510032825320165466937909059780, -7048104506603402033609414292003945684714202725320586515610513258423293972116185209829043834230088292070086432810395585552727978585409576894379912632725851328739067043289217116794988567168206250690721424269910862271449445492678250398040502519863782026846912251744047391966965027517498696521503399641465004119520630034476841951245692734090536778657710824149354885764580536869760222108234625414921455811507675403411443, 9260833998784801408057374791302312091296411984222100700742848804667071854297952795312604332611602728767905558048478247536417550110404533934924584308366242113595910662989259777384356722438405372025487420284754585125707089450069192967893169069882056835181597381307461033293427312197605641219160475429707156515547186144682174854545718109378262725785292860457852836832589766054375494989782923257254254062415514341218871, -11274559137750673107242509546293140680248813267828739214953306107389862943431259236809194565627238381590471759972868026799124269635479195337470395601601214235600114234305543540127149411067734186799218102064583038965049760266493438732140989004103714711690447294456646689350048155869851068888803883485516220462705807882418956513488998826353455627453245898255681591298713872409838862737640668727913654715459726518795609, 12360337824138586731803728880282499697525821072845513021503419549603736209182137047226551596646464514115337273411201077934631682708941750136927800128575206269879516631290087288208987857415392981010215334970944556488086979048209653697613199711724590687221357288887819570913436146521712541247048780078678574661058529347097037483850498325011938327701935972244956858556481318162061329901602896579979347724039388089542243, -11997407886600283319041102978211698763437108997950395143715594521762461386020969851405469808132777105546944155014715889160357885390048844399807765784632741406806383212203075719714388471991312669396691465714254244892615046378638934352692151748143216936062309464159439684001128734324874363388151800775004643951616808981442869935912799004437210562856024004412044017366330073187699998226428973716750625671201594757901334, 10096315987222973604628603725027664680250304218168745406056375862911481309365673717189685781497476619871480520745415592777428180305103451482851285116246913174440183413560595147750646167594489695653507983005789311505060090395322423149173420865197729107640823758479082666804740293096133581676765955377757989901226236334347841099471874904548777557415086420094827815300017533896115128932325511926711491628598361084052382, -7048980920313815592395316924196527907465862431926204008906034061827146254537249907484981251296509006376644372048298769123251619441046809493925492942092742105769065025808955595119080742094345747654723124901623291823618502904400966449296238665497279051683388312590006617187523513760433923662501108118910874176253000366305362258453012344128621051885892145843991169041709721879300414132023803252815294517427232273990085, 3585702571503001745311168651893409305555428082285254273977298611475857838906217039096428447006162118947210862527547751483040732865709902108296243110876140905455765873250370188002560136032040991011869721798985279736173713024658420015364218036701143049003144198213534951563500536998666551610389630847140712652401745773131044711593415845518598116328122467729826788824792862590693232130142218317295095285778916207901063, -508549439253992257756520733453242511641712630828087172398341675197841936469409781554806499193631874502327384218103913482535930676079048474397185846995031704153726185737003580283096811150700877268527164232521677497277884394865020890166055132645084442952485054011545189611022145833446944010253452881029733807583687616869098267017883511594734188015630147746208953476466219875692545632505811679557433051459597737937107, -1579180385112734195955636434967447218478975272786099956160065583979629719533341290321697926257840368602943546994866701660019535936981747348348653395563837883829051254273738181923376886656992000182638632661300099132052251037796827912003565050738373676713209605686861341607979968225233011006996747805129875667011466625470147013476540856495998688906249352857153281487614148608768303307681786214273346372663224543204376, 2438470560417845358220137533547678207261559724871876919782416885238214197167465788617237937451853941968644838566042399586983955531361340206342122810078235429710934300717792247925278021025417832448526949381839221746914282808162277114056877138795774772270479338354339298485942358665575044326102746742410616236676146323980588804240215544327463582575982949913965410819875709315972599737144633106206816238433974116844067, -2205634239036416554451457783629596381324061840014760687707866404759487876234149925336881404321237927273462970697370068114127874215966532846824563127449023466722992851014810755523026619117811703120909923315484532791941837720132899432098418539439809492253980794468280413607876943982179085220753374560244370731731653294122611928854792660579202830414126600918421613793295255222625062269950412616242900230282196211401108, 1272106226399936204733807755696606658353288649192040423330204156918835807925188671580501957948998988439047780284348466407021080184093133738681472378962004885132652487120371915309687596133389243077689818066620967674944874105607328789565574583133287852032195766711926831909608153812626647087165570958857884379140680651027926171094885405172284298833181092208882429443423912602274970110600374624695359741221444604123356, -105297590142749370790104813140308236587353573003325217093857276961630229855066551970423787416362826719685744629157103292048395746871911719648052580641712239839488838969663326049137041655523700718579481110843570373888866076919266934074001849119070595091874668610247630132658359722906652273709305128845808892331865460408442960265801539065414269835323793139034740819700220095802796243786105784076311510425255598311428, -909811125919778457691790433798394529389538893165872864910349210637437663922914769486558666144241247238594814413963331582215206201645417645813786299000969770184590024897081145441685115439020322312654681038367187811924309819965413528024843228790673024992610502268050173444756272010089298941901092294432840278723701281503014272456615875278139085531253694167036217118067226724202819739569240755371172220277738996644998, 1557028260775847982921289018540786725963428828967759203836940231966180330085361578156021070176249798505226336241609688849563576487620051828553330276069762839114893553048405796963852894102200093836835746813428990133289927253559440188547095953410425893041045095680166714137236559997835341620086420011127341262744766948311465944859260336790179848433401524863707022708747770875779962342908616737871817975288977111885745, -1794254135905350755173139047065289562938249717062895968292035848610856851389978308372473113939649107465640568947119471592730492293374905072502456265403345503813198092984346804019055715647564559384408219515867942362578521765900121344877519382590633781478052761328881652434554778542686733437017711624275746065693567473227362731493717502634999367047500668602262286942233728515814974715857219265896028034394192141774049, 1702306331719166244421369032467065188871431105155045262852420302336618532282772479357930744720919461494496494539441913323536283219139272233282608734234178472808897264130332226811085601687915814320487568656077512084256090942699898704532060677977995680381383749727929645388788430382330035125691272302995372260749795212427484453829486913065772988385722202951741820829644956351305124932662082175760632192594269417375907, -1414685406418660934151761698780611263454755018545944899030466737900158203330563726732994851391200286517348909868807369414412341458426688312972198952231843875509532590201894831367538814826814501680607087617945292561492235171590660915523026512282771472102583987022249448463472772772587621163543026943620901608967954529906516475019729829468617101748371896617146234258889943865677268047773342958402428745690123913288254, 1059124496900181852577155601467319971434974072142293516163037034001352990457335192453617662306654817992040714424416170674062321738255879404008507409502344464829945549956046240401744040247650537957158165313355176031916061460958458335245215400696857201548222706465149017483352565946873271946134763604963082575816601997415464057377049967842502194264405501742386004515697060277212368272022074368270463814017724061199103, -725488823552961327388902221405262522388554693404883874515466968092058326853418200784578302588401018076103597034237047163928618878396915772087804043161748828835550017367414690787569713425801934411335357348871020958860790444395435872799391427473852262029781594967351224142254973294602123215751441437299064304179593242269841852797259852317484525826964932968916034382349156254437982715082502932894128229745135923115220, 459137734809364949677263220239988979161334812584674582787349206513621144379275880942171544520152643868344234381526001298479378278335621822333630054554325965768088008567955889034439776034304618944967382332002140967600840634510102654602541686426522721310749902104907459639057925171955743035765702696751493150177403219521968260033878264846969910498901415540858203530425652321970850547891240610888313944140865835001537, -270289875579000133895277553932561777128803883820557369665949517438890977422040404322777737122294457953648977112812753838695380147344152806222185016973691961264221243857894196333814405271302106044985845129397769603099385142659758064893554075442687782910191489436287207652669891431947174366112155751318857438091990806556146470865622379684162921732429555125650234953969149312638694771854043634207189507290246393949585, 148772966016980304319943243513312409213992534889603813116469889680804197166101339344818096562655519317881393340849977821763123855817498325820347571141885054290968195616943550564739317278582305319630056012643114684461831697358260885105605694468697940995676235122332282441455919000852113828738956320075132010297750343889831692265371349561755323972569324960441920979759239685838152824126289664348564079324690221687055, -76882761632435508700279635604426291403274460754408998227882229347327872573124766714003725873582683387693810411134844450618170339821178961564711246632437488978223527528208396795839636899259787408540255171471301578776188484887910763791815018351454307463894356906367281686661040800947757839677999849809248101768260341334327431615947095874084745163919305573627442289585077265163995096275766330050191399430466151969511, 37431675194369916831203161156040885499691719219920094218650929407691868671426122925704541863723285994904823076983654209306713349063937903295181431124241612508182346746684593250524822289711117798000865205425933265667608471325751453378048154447739712635220725003460758808663563321465998131200881030205670319912406796442471920339577821446169261550251619477514684722108877018048726930776200698015706978978449929863296, -17216732360068751526715630748776472278419750522660747806066572036422750755564620670533777844916736492525322817532281489924254301135515870456006611928003499055567439881385837125002426832328230011696780960042932039791249034381847225262586852990232400561734811945578638414617773717964358660181190273921300067948624485067825204119898279569404050592828840689771997854086102502844787457223049745421934529478184365247490, 7495290587416530447025728626288873180137889883310472005760823350417978077282312008106245151962488303432112176880865426082987828415324471351686554869659284763292263802256423761672810820205356978080017314042301670928416788926000104221078648349908911008615984657250661317861798776367278108965693396946748944199654751776700278911892061595883909178259583903454756088456810093428494273581934196698452595603844820498810, -3090905971077008770635247145187215480226349734973271753977315747151242034100503197198299497149046773416965548963076540275780417643064903658811525059861212411243951944425491293286662085132810404255532445100952677784629317720516357205522090941028698783876158720143539462580950291159921972983202934281490774218083196436119144190490063821648735633842722821609027578114759485211492399940629615907684670615102466675140, 1206586381798790141057973697747787883812919475474176594890894926201254423082863047497056100964158180104024760854225495031018380608009839028570019692000923378702607161199112380839887794868649219464581929786750497796267287994123948610676483340821821087771567586009249968122872856926019892564172697785200153416142285902251402838984303093701452309319153881829449300933764317508754291247496329980854344903939698718332, -444859291352486842573568884704683737803276659875334692419647992452629213253843729561300540157888136871112302304532141779572656515243738792582943951418057918857844580501626808071034123852048865688433055282592050259667464821222965774383960689711171033376966815888921503747283942207361042835829140377317290373605466397761922918747961166070810260945225386729157558859438547366105858186847594074122988744908373254585, 154308780355684303463736075317009714673585206286204634316472273574938317116415994588446583853347409194660439637297171691517046059730818267308850716076513487797074633225078848388917687393838868877770732006196268068060341168726976191545590022737415471185158110201098733547593212342430715416633854037609684369409578132305586421425623598856441649504666163054368729436921227638803988417211856673732309569834442131601, -50089147711281702256946352829276558151419085682569036723039600508823410941417798817483460759393525523764797662102764726190432085947182251678463138276835437405122850868495618795146766962654966753461359082785242510033153265634306053693688625053054746014690326026076884088271987221645959267710648525400815690726370300420030824057058743665099589195865082207981141987967439765714624865699591069347318522763128156177, 15116555876933607129676725528158681691414778255613988082045365095462391481523810945076261015189091705300949850506783628763228054757091450568316030027901652825223445121558566144434920160448081561059595578322244071347148069774288319488357381186775194945814985457459806238115131892269673831246348094600534559291802066688744423138109252309358060702347938998828532099576833887581115964756228011464066244334339716164, -4210188947503550930000297576343849717110907948898480467679325466610785115240181716384573885244400591951082300161647692780064695187736055960934114197065310813688873442033999356289509368825938768106973665801488470440019708259096242437368565441920564827606744756413641933790708117400795758667228184624729758004230386229261676002493977958760164613076297734138908434111856083392119821423201535658820084983064549618, 1073419620976739356990336519503290844545663801532109763786465017904166193697243072852338901401040296486379673610804713080816936626165696029139441082289524794806323511145505168677911839391716507486425078385115265112443631568628351369076958546015144036818514403418633875749774942746260160465006073930504816514389267699431891603656676526012317594614497229441949647225648145978541228558166597199796585786877231990, -248345505881368622689996139483536082844147174774834514638296263081744044794173755975367474541691982750296080150254706397944727033682077071505619402443024161630768442056765095867241927116802968129012677043915109381010906687040065807992682468481138785803341341126178346008589238750199315726920545437682710803868625770661494464601341271472620423071633150146856161718796655703137025014623042814692026266503025148, 51646001542812601978275502741765696598138851912816799365271645213440873669725056806096504170354991878118564587272269940773071860890820706987551963880576490160882015677184922906979371449570649000420259408886198229088621981651902909756957546379924665168949483919903031321634363606057828622051609400313483554773253531363020268125337494205990934477034514415111571639840125715930756579477825898588207621590255931, -9553130818936359264948882878960794378691947514493455590745096956273039359213840743089285544496271512165045927011608782478491377236102766734860419952737146913215318606076677042501426084786908029532231789883334523638964711524265971585377554762599404657951091480800506061272071885479872713688757532324723699387284648604424596046540042826485611002892976882370814408716845532051977480434244500550642164985095329, 1553054730756837789489060867741642984787056950483429319149545271429541629402297699475360099697328223426981360221709456254128955305029348318150760688141955695480213113976438370543642995952744144498966696939205376403255788984251048482707583005294768653666770578534517163527713951558705593620253570774424394280547090343117538633110867439848554853771120807724301158154939849670370982319179155583775764700905486, -218796760560971793513924398554489889378244666270545007355126925482252563084053064658204018943532274035500003313730857887720195752871390897419005616614042434584348378137198556347297722432324920431807408392209806819391667498624705071722995857260495740952674233691615182294789928610375935859514671578783348308413559485845925795038763978477356874669261524720250381287503422604084813653141248557099848702827870, 26255829980897629981131494923189401857117327750920062056093619945333461019844747277037743963212420724963924824272116144286460024973890909798752079322015194533956785118900967165769454886503280600717315321250962880616598483150907991899071519062318456206418566321594214931331656886614607345537345380530264130752529839366930151523280254292666305327839436344146598750249971465005110149719794596232027940478185, -2625396758801934770255964689715386892680536267178476707441861845101356581174038485310661822062610169858213908651793577601200713788306910829538863602708533760896165564296358427583263004219361107991161014165950800420071617078525090105893310032039156610982009922925736566196930786540348672944623670646359861535880172493270624951135683580634296220924389179563452891569548132777645137659891950735778025990239, 212393857814809675970699356279161733419704507240954503708880674266036770992368694069212270662343269577401576753728215280693676783138809995992156477169900723868708192266258917777632196241347114934140733563247685538175009042373281312098511289130190948914490583846617810195501791838908954102659404358530181896532865413867543241514410119695149440695816677371394018527640081453033977176725078548754142270812, -13327529174415965473879952734756004548205662688151068294574633678521550422958055726799775964553256241428374555876684980663779265870310406501757813559783779432805956579699692248588855993372688891505193303866011749652313474473386498794247572958937375313898335686274642380387635945709596787304848437616428356371055332038678997241182453793456371372363675411822555184565844873604261366653393760756719549860, 607213425393761277338690015680758983452245529919714326598416159616185305549296630267764234432618965430247169172474635715279790700874304838013857844397017152747084389746799522114937592099591297567571582181083302239759976058822746211453890343462182183380914391212113525711623188206120504702508790409067476853615981803742652826593425459987682655434794069210802162833322234514505341737575217632144677100, -17823828401709881966498554920144947775565152990707277150447185332315723269202055060167999422508643362318844890109737620869821857683099300445855377104683010049836301730118199195297202937300309982778639788465387186516696050513659891205974179310612517356960639675045656701984806977516665326483656542478128310763925496628036120935063117968043124555338973729225590640492791867531634633866331354535406000, 252250918168499583603493542935204265426827557896159025753320037911526442933599969183362545568540295873821809259064054631020511905897050577101351759797247752529778649426876244681024596982811940068126557590656754108546047857808731341852056444067319510142056011545180089903461587211776605482819079745138816731110314616638945536814063502207370037789690306661266843507547078734472358714033621297750000]], 3], [[107, [-236217610277369687827470078217289876280233660029013897129827081112940638030242007332773783008253231573230897712459352757645675993109749040072191362080232058776330988308371515126522725294689915960769102963768478330585200089666591204606931226184862946613758961647370871281783670569380332845422988627254331174543282121976855600661749014062945471935155609990316498887272177362573608335696561520911872, 10217522507924471277969081729005764304261093855278922396119817688057442395801995040819191928754613218704941305157019433062018338132442166572261302782506602838866671421990160056353697925090005558523680400829440344563386102872777132727383618025962604201133947133102309902468657261983528913964552181653390240908345209246663665668316664079962354926779069727116389024196908072951523685549797139135407232, -188996658199071344614952698017296969567339552483921035887430500268473306185280892363978144006433907835921994906910905454524802953112543283008046592719784760174643826693204333311504578363447400059882549219863154436245070654443003358958092064895732697429743568518406043653828199134304969679132191977870791056687710525106579520306106114502638794697932347898686894552151881060772849793815927047934071488, 2284119892965724948546085157775286690514579534330341865699730182305715056506946642795870248816772697197704615640701583993334753860091891484282114007946219951474314212422498764986636781955573067188959543111327938858743703935714626099127808431148974458511155314663192001171620628110489411781741460095846310434384754672875285418081811462791000855433132139722019041012265984451377539138219659342659245376, -20783495750275962339601435087646812735750216124227631978136120379481548770002505146736985880774392408303205245793868986501649652746895236805742036251413546655558411893654352111664706646335096361419829812657236367214344654505366814423373912282328179839838975669048547449408123954521264052714020090683421586595087703185329702490847027312411123492561562564097105343863612478316033067219300174457900599104, 153560439600217811119563210263725165209427167438445582269927248664521544986647034821855156368674536251051069708007827817619695354795201999655199274427882570553259803833692582625657598371921605863646677564580704830812736066225876500610800313347186262555213226484364957577428881985424067778873189382376845117689036465142553054204943361397858569835607074860237201985792480864953652614886247508784891783032, -963270552502907142321530994555136777983051119953323109457942731677100151323890838474922008928918826494222243482707977690460148466417152948143270913046614405358475143961228550840216238729175757629358800007486124590490774107004444407700090883090551084730912373441880246461301031377358963779772922166764331901188712997393904350813122429521198399077048811249921956939326638812589611487785501813697411234084, 5281203541416178369248455835444503081197169007722455821932747042435171011272933941995322646935943574594398026181320988630882383891953983419547977766791611545239510997456601430633129229916924592858019169712465001594704504205227329309828654403716121729432487992945565342640776432703564849120636757821325024176954956457860590175401741129897636817026672150025886801383615938364519656682388276774059392453776, -25814528249631350829701735380416003000766009988575998251037997141283990207797476962325478134167623819550067692679545574851643437142123621072140268870782597860121383217459308669268758626164867958283260353335677646719800818404267149551873562458423922849430188959886851817109412922083399332430350060780105678358166850538213331911949338824763569798490441122132501199298560446270299345216908117486277105857428, 114124012250613963245976548788607193251255760501786083114404100365928909473850494140337351359711157603107263820186863082526579941540285669965469139005446648888874666855527842794676190203333975626637250261561344667403131751156261205099867163689920952704233331637437607787537422485888828497015995301713130099975761527986955836951354815946068439747779294741016628398220636261014706445393375706458016641294070, -461302907839073501384240020031591935782597816027762829306348269519387425120305743791990232294296917622471350892835457261890037498031390738929862449391412784025832661602033661044717306511618225920816052893308438340558635683862204850747996931711614962579765279451930246660071520168909700762315475412406753844437961738161956329467520558240550002662796082106698956956801027250032888858653832030682273029573691, 1719555955363973702870546928175207960593997846303549157253043430095257069558264400535478519669840789228056247217941400511892204655140696703043570032712405445424450874293749546539885659919511327838799383692783138699785125651728064228901684824352902646400875223839971347407301010741924065988311227081942808635173605692956295921467801450621335219035006879324417590583174207558403557163482369306846464545153852, -5953225548131660342136403382015392557677758700014915172003377875926332723027016720499949243961692951104370800098938067241086749024745653982759639516680970734134052545032506845742791845939784475948809005093861437081850435834468118587895738591171689638206855724609980818391060170654387606774382998408886021760821650047341774353559483436629769183866327447745209413821371510662879796308719729995369670471552334, 19260687183818191591554728040957560968493887208767520321062387460445272046823397331162301298962151066794875771331400896588054925662065400031312444279760009227829307919489870355566826579853795197135632463722611751252397212240131381026929419739892531632379248278552903658870193601833607192157184180643076009983536931008546630317956664237180896074154006670599511436878924124436578026318156108367975016338091188, -58559212638418772948395374961258975780956677609959629716371915999334789281535902841938071949104650778009017256775986065351795629788617143510799526150060638565010428878984966407138180158731972584911247796871774572139836400990883500065511886240101057915107548298955116859899198561593543933275471719093381168421124578028779628896599709930047042189926908004105796101159707558907534574597299233858908254099999268, 168180187154217960327558845455371289314961485228063442896000403999018633431215927695872787821093920606443759646944948947637905498804535301864360702852921198635890365577012240872479102369840502838959387434702343590492169397427487084886972171064359019361225891201499906407778520509818642627796956040738466662220915382134983491520127650466635277474218140897793001954078311187680776933390178976100244525152708435, -458496524395747650147580498309672688026886536997432936707791542059145516767628340341898814575062488507801584185176943952451556112947569345537165752766241831046049027579479515775538023611121037917903642641649672896133897315464563625522964939975829600622975310390205525627316813768223374739845386267817601078798882533600292933089870866296089768098343054786234867997784222581399239236711022175195591006164691576, 1192021833818175984068463326122091511352562697968034021628955454060723420794864721065700708661302946547764100943026468000964824490187968627214184132362277847178499524158432077094319403422873302327065243862914721068443212002505064567462502540639409376596644848564689285044683447094273339730519970492603632529359888118079606901396724329943460399342746955237461127232986180660018273990482435820566951543710907722, -2968121102312590405980849592065449531573686912000355876209311255676076544239211699335352448030213525012079595351017601660993780003199483914367751107331104381571713875602871271538839164454376106241010664937261212436155178028276376395201551760378490020702109745157304776851117950096184755837277064346499590041112890698145500586686264965843979742464386486560404180632746436240569206609229734379014823755385168210, 7105601544437737965273524748222742866714371655593060900891917234861583484229985867505373339101331335155107718805554925615848063911342842644037557324452005469714390806294867179702604034396377390113814721280183949093566013689469841027199486920852638632842470104055958931461006807583349562189652124670442775773242692875962574581482085239871064183569625142168918202106276485212062133598110408368915351546141433611, -16408284284454375794134907956854117546231568366805072569890263230216132016688619431573794267263617718731640597930678976481770600633508130786698378623194887256830236877960694493386830373206937022431218817414138894948457026391692122849539249048540278778005729032874326775064895791969761546164001345127278658864849688966724542528164707755403903581082345170969153921644743987717504442725382599648904070751793645846, 36641635190089888358793229675415017730006402524743773610638581540999212604450848952537295312022926424646375290907734606544206345023666569099803272193080862973230081858876491622281331296774638322028291090663036449375250842395493632648053432093616463069274228145987070747766196933290527148423910143555010184393630337690548133269681232009702426325211209109408702198882517433662008662887439850112331452679445541133, -79264203508239164347528615986697481603052708835921942711617743120539274117942743617819824695324768440433604595101694889821910325368883713059701144016799288113060850525115527588979198668907431871421305300549502492638363918591835597449033114918447518148560225626041798986440261288521547871485519715714056988218230880733786403605952446158474603641031386783432805858660459651123816809976050979450713248044647408626, 166235485745822924009882327367654531553622853301250296765765743787640321069292447051779882783285069663270812405202756165679405585677617092150852009466541166381146281926821982951792745952451735176093099864992014094283682581072296646604261432772792593201751523083147046174356124094908529797305970802882781528389133072859622116858825067154441919961886173480715596620610560539758803382726960954315428926972787107260, -337981967845240625975528825350862714090442536059271437724037648991730061475823046496338643958335922844047854180426441152224401788772870941428120602945227130553765580004921675643988599490780747672071696270236301444099021688810422703359019734322881968626200974005787322329778141163419769682395380674178887717978040706921715901663501940359504670272392493334788235661662865465794820047339925628124028603225726508790, 665632874935236369332364668972063919348922049427703065519553240337554573194854214383926032521806162075643500648246600940724909375745824896382303913747504476628148575453426271957485036243131432405744181589462109500698283652094255906078813845350911824548147601026367160547713680566650874413626483104478995334870800516254198853577773891282542166174154744984660388926491303068370973462493563867097802264842521173988, -1268033767584155027856667254308239366397095942878164355877024293232098267514856413260251848548475281058106722500402860611163928700874936343355831708831807073525760545424065379174947771505101701991373511631692090185160004964673158800427714464454543415745776337104519114921364281305389621217485862571006211719985636779214798844504202338604859985006535365766607628374111095874748946265690035896300334721087453186255, 2332233006874353084278810378077041249802953041015616056277085564274081357264493010770062007127068678429659615023773947826532350278371474585834581664416654216802569013832825556403287994578697648419686290893894363669739963619027346723869714322283678014428223250672325834498122501874713451526559288022414310590847386968088969440356899757656739901515885120280673921265089637935367488866081276647120466323562117194137, -4132565020158055450031542972244085049200292838731484163443610177895230983433959583761003922546125943134805108005607861472370941230778409622037642561779090969353771732136798448805248673323472173796493095529897005942163766873389288338050819080768951095035639380493283210578840266358577038482185964516891867369879360452781276990345131802301579485758737013536536009545397860848491264126334252415517745006477516531608, 7038097997328285464306667643206358857665670110733822483910458704260956515028888580543211286831415035052632157584606129274241574376800903959419717764002846719157562634655594956827045275819947521430102739918499760775037188355840779339923598681264127021826360685029543631931852645734150528325347973795148542908323665495113989836906500463883370318667023355617064315843983387317220627787194220634979266281897918213093, -11492317802049618215595308133129518610996998542985630865885665072252754259440031828208801158480396537097960419548117844907337091188543996674751053531991661222327135600579152380049908189018231883617908662878614355748004426952933885849898432880661944521019250934929394702128056597465381920047732546085809152768011624845492279080259752751831117071100398820377911925459488277875956149208066119343641189356886377643103, 17945664172466698576153905833150679606765434078348312207856966476387169121851093385742858093467020983621782168734733860493567433503322801955016351971003101394074640998914053189662034036799005171551087417388061703726765352844188464826427367541733424238016781134193485336208464683211234171616303509607766925936752047453548207276620636186543493079144929308009969517935955567757834208800580203188449882018866203644168, -26725849753691198748250167730003890359116066276911478453121365201280883193897058871669964133695340111071947695649940465117474147803879618150968656170947659985381771377253869961680499167474688238829295104528891639553001349938612630429393847941312846475811001722803056793978568020869891678464213739275480099309599537363780006577794548847163681760786696066575136329007869897541588179873494862145714386910308581586507, 37847536963342136046128769663279333481816183370297065694218947326103854496420690407613877303683477823554503609516262517901450006830829012436725832851325790731805049781009955813244793973554941231025345749264926826886040087830476180224563507489573129614790095502618013343545395364011808108114348033073648018591852391958999066936649335778698857885236089911166670081552306866895600749852304317947211483101318297430733, -50792608101064175015189237867803571450518491341709015206226055175325636305809253909716333982926284206323575686620982900380055397229732592891258220918969947300398711338736217202391518167626113712877199258872075926597319365018031658708041541662573523120106912259046911443652758636067388563140251192687529913684527268109220335459343620944276845593250383254726650581328729587376614177291581570792374046631323661022413, 64327105912031520038661252389732378668771107817561474419679921875851133645185149144086512336797667572391671242903493305426210747740803637023289640267230840518037662194984094144885626355387665385808828637262224176609404107486391004303887261285775980735462590148715918855107551995250723815160396379689962698378197638685069717057139908629736785052866076182734787427576789798584056920134312803011365499154797374567581, -76443092827797038310014470086190379393514862491141318468014934941779127728847647540121653083625540308241086227649972728868296373005821484853915979031008216008971022782288678116175886185104422765395448560703358725579531976324645690019440358617868414599129358812203405114589621004575611431204834523841639779224371374321511792322144729349346427486967091796774774672948234488752458665371823903040012883835098298104400, 84500808783286041569910466995235524143450807362960836182105977517941807508027191684054068232590585156849070275176773181637247404778228653339423973205139408426689483875198437102518453298422244541294215383528157687691040084597091553521312818423796213975049573666630642802210036356554719206467105265756156998892647982625936848332503513856317537896718671534233509962086130927265680345486734999445277198376025806544372, -85585234897086322942791767248647489117815179880660287853183969987607577292206661518143520173219050289642898509813422892371979530766767050321022708232313625528056577082261670949900692477152655902764900989397338047058202555699401908974292087633149555085947252980509678956969988487663148243831036977592101670492537024779258230683967475704520936786451199147806314109942247353008936982441863481235558534984780246981989, 76993012326894851436526811864022038508497821573586791029611874631268499401232957552395183311583124030840640301208744642211058948483368717707408691025395962780226791297725365586774508387020208793151157509748643473721512055375251498252182491802946066859742453106102561369547180334210305123301986840547572100259531859484305340428835998409463841830245532909143514338574615487808792821265570111238882796119414341116179, -56673195340230082301053598381528850005191488594233766393613356767582796161474063661827132353946737040722200500552775482782990471282396223470085310532768958019916295737885432744228019407444652230804765505413784369997598908998532245744482294477716189980657942648509990921572178422386052698528367089283317797294511620909540899575022252253978220498141550804199603541051415841080739327041669483467707451055115982126314, 23417239741610390684027875974070796740643435312772189491540156164015685605590786737041502565802925472365205222770906473816773770326408623690591287567244775172048637500174801471381140345020900780544231046692080633510390551926658909888466294665648918789943305852361636973932278673085676962561460487744966858983324147531901516830787185554719094064706763327961332033881698352985122456118855796313677823252355210590286, 23330495823018933814709740011430799528736443754342734840722062707456560276482085170662127226393927715908348176094281519607753547357000939885533666662158267794757726917498981247329561218887496556162781040676544760340771040528700961976527088427391355938789490252485007455818756318103906928232931859477407983842737176792754271304811652284258276691682912321274204748614505653200652768659679770376229483512819352245419, -84006355124479587533624141985168265772885470950294724787932776878728345886896634889729257548186431709127920693947654988129209142706837585434473639879894804326157970796635130926682332149209016997357367158997972079391829002037712346258443605438080462370471898989325225796884470657828562422302206306962348340500584008823495288060166985930069600337478058284755947197426685289803670883692737566960751043447305198721797, 159595394329366557001359665423803117275299442202404505900578906788800730307286965497902241977800790102298272475584129083413090384501186140954583701227669614629128805847244277429166791121959918207750525308540411076208862110255555056023665415290396684513098557684945864940393203362085359869642829901976064225855542385423281231591786876316881270536239045055137630498145985505304184811366263511212726902340016548253224, -252140153353413441885645676662115333088729003272445392334500072443509930633809102263161349659308062781669323715380182359782966574104817364991328147058947773064003175534974020846144288053071665184820775733420366413111095959326405080923100608427052136451888860882042625565359875062577649836726852511222123873770726581944388767063250602214599889024621414859071988651928796446814261529060142566206853567172294522654134, 364856925245303816577912015581330760901245272299021068047974239274739755546227445633330114948885976393871201093421537273842544449658495446779548411207895820811415156247248708155017669191453785288504096203987400194031475879148555582916079428041420417027760183388356636479938729192800332127774215733250392209398510090270623379411125049573747831515182025594120887874547664506682503115388397925272467084055758665514849, -501789491185758648619330770420725761325209850955809247446062934294022096506967159159681180883725301157886055137049439977390551369006778912290289963447500465517847020355584184692891624655608988540881653958497079486121433676809457805680526950446344684033467211657464269091688278366264469722514645402962978244785968179375108519588810314088360384130961655123131806387000360598324413542351025271327982905685357409400413, 667079587903574810135797663273363460907015299942258624168406312773040109368376295812357091478119735338648863146890086059755048545376466091988717798052264532503005002135520849131048511484099034891693369802124387588796146422873745145539722213025299128599022417547214900008589862705272644808694761524137794691746821524326079092471292390144324117755373855199103455537049723293208332588300188575787639719221727635451942, -863966112528482242942540023866852549491771538248631885624963098426485093264139824597662635110257928765771181280722959103059191097723593969626577372846252387161615821294367455802455120863644510584345081383443271118284330579934953123922880428228969902053215622877201572424142565758012731011164464680226948610438640110396051015025322094666101329312174333712233507654894561777541765699708661888736071429674162967623733, 1093548046608504873551710001536189601589683946378139861832103693745729616604519569226405880233214479955566936636216032298551501347746712369125993584909039330650834021775231158630475132512136742129286735950769458759798504031586471903426829799592726561971490479443436422009707851827011846034825186301426477591963264739189472562575998669882345656249349058203677205897038414672434533599798883469561945737781704158375503, -1353289081281190137380932207741027180285323968021286010537338219203212180518623067838982266366500678666945309870675516337719201288818159783367704622647229516255780869507141856805530604652341950681447583984129131416129632089896118178970357736573946622673105396330724762861661743841997197120409545330978076745774573744081968478035590931716267245560839026983717592396637703114027578036023889483965139119444272103447901, 1635353733397454284733585904879280891908477266942740311117213049985946236285301740244612038981792880825904152449424374499818132959514005391304172587964738642002108034397133501192410641281991490610420744185688207522996111629616544862432358255138691747062403487321602122253516870132533104532286167528572133979378388373301481123370731070343904246045065419148304495287775818954385992430291082285355296208315461403284268, -1925156927977276821133989642454957336631573933456232750421033454094162443273540977750726479651076672435958196176917579373378417902301010821653393734682732940749867522036167341830756773807085423130625393294258043574371896524879363055579285164499465910330383226591126163957601511359801663868031569826902849286187917617792513582975150426979374065727559349108544791490807897543248768933797098638474290551317500823796809, 2200782703404592133808434891879528850046957975962337393938011387015022583737108976481329759305850851566194102541473887362346690904036819397384196220920937699538930648095745228542872933525700435107311488148340524403324894253506999814932290867927791746336536253473379792112000554496329941764712705806882612363280247010033558169594831166859149732489917094671672276915668039373503792322542839296458694683046783816593848, -2433882983093424714949089269058289566753840770741253601911074721604202594006817889872714446397520764939060852110780200164824578673924804161965629539485950490186834914574173463154983321927083817622851338664556753847415233841573767238875574736704818380919301787097727894974491196276069510051255670883306785095533156528484976848336581889940756221297740321149303739188227604096156387454067443005126109481880622211849595, 2592156313897883910772428686493666926163444489427042833923236863673126258116537597344752693310339746411927123273182653271381150273425176479645027690929516665367461378277296667219516812687341277333695990223878858952203387396027042415927903617981914490024104949891556265824172317684896865498637486421696230307343644261959248624560727107180008656069623808109241312879150414684198485330919623034499806121810577686408608, -2642743678968696839806045938650037794760704956552346897805774532468761412873186922020819065204276925732633187825405696787194644858739287155677188688861181884638912253912351602225885547463810375683276480213435119424056529250860690756103238211961595728838417416935545341972199271738130801578865315248126431218392531385954254475978395270408528148662966117415032495692069609570600838546338499099285856061160172092370960, 2555398028044689821010636967746089400435228871413627353874185492385795166413723619171296223256777267142862934287164762954604506390370217949088155880062122900753180191655755580834857656015865305490112934531479794646612669450662877552233023846709291401896083191400649611928612054975588843464179343022252070896617914911142067469845402423504532314060961951392038427664895643663384514088743485361975992518721163276459055, -2304587874536923284588878391421246464710890708221164654998942938608583637015090904853097943309306689333492019832597363374878416267506860655311724238729708044259361280991265820290326218459114427354786623021926047716890936049911721610076165860009930717384587686930596668508959314342092090515599768617674718470013002547250716228484380518912600376269825568572824687825054508170545634800748361302439757860829974474424943, 1870794183023260799882134610708303847107658980376227833063206613352293708066643236228555008274032453446519259135941440610497744989566698937711126583924171709598358601685506144453365984585787749125833422681131734153738539442643284233568490027852999025845408798198793170023391098015844436564429094350817020126853593098016293584004544750427663915199671241288786116039892002078557686133221250151657075206595588938093375, -1242474408104776080938980885597490634778613453090358262518048857339665970638878541244347665825889351276306716387765782262260150047067325478278741060263532008239559900915943504413429153368094951298235020726026048811083299673314833972015047036313503011817272376395549413628043787496947480900679452174135704413845796327553657046337366695103472899207805436807051389133498318399620080729467588637581879840267773784356251, 420450297642393615671301260932470577429283414313557659661160125574152810839697941041807236872241024250882909272497485205990963838108723444287501874787911752400304027619456222012371113690276770605423311553262642646970465934063034041769057939654002919795483487493863340407929340268470316106599051699990557025036647684729561768524394294662310569891665051392935020403688557366515859150633567820182714293877471978425958, 574847437824191636643190710253542315942272636174936336871595329287496416484268541618313584045029556923201565377838123867962475684985221924797988591301540319249609501966295433210791213343845478537943951496300408833397675175205838081009151113544143529493410913733386032750030356100022857230680617952689330841762425583008009918698416475251760277418205503693274413544311399661197465339186603176637076177809561639824221, -1695402413266781396126346445143210843088019454609211123689376694724108048320139396705454735377740367421959592924440699988805686798548613361848215570713041476292606738914106023542339539859714298090135975730480125250294231734765838669626858691685160920251378265125745839709259231962776761043541086639821735480681765543839385501182939778071550252243975761046897584344363793562115104820023321737861400053291984074687851, 2861362551913053189145273494717999613290254056513124499552121173502262932012157856067054417451376512330567795030884387899443091114580380539208400244844076334247348592535038909116349730219062723211585340006095631207033482360849689285703190873061748864916462902778964116990869002749316849052326707643880950743854075117035052920734308755972654596705343581120358882789633383501179608677366735387441610858144455134454953, -3965321826846571334924632278677075221839799030704162278964185678291946627263330424473485336234767980783760323143315983048785022348350267399020225960510529974421858362289641909454871112870037601968875309677408581865091848190051697920702040465798786532367927353037240693688225229782906025334993824232085096998146246802331976870116818585775994080683995960429938780641885545451121846781384712004100613603508704578623083, 4887414320882168800765836391715932090669921534428690467872738211912167221108724081955819809148065900711578428196608632879847530621526814488463171704832481247793300750347299206728890025916256627754160965453836033855797252553229143559667899423307687032013221350857104746982029978078544261254051367123879413090064171182700932748712658943421076891536423036174410340025108199538067686322242338871028024611702780425460516, -5518891420115995740528654301947154513317975414651250995553640052095042060587065038333904992706020349594411878271610728516420993325780118160522728618209277649605415744807781426105096222223610057855564102730440083721826824127714796241304570488593234533231767999907664529458845766910303706212131098043761245033354846047854175888629627744382954979446340156516613876085409976949941325390413597418594926591231898161437690, 5787381360350808051571409002073867578227522864166519447541217096445706035738463298304422809606928846427500499281069726252971545122089624149170189403172131616982595395525867126773193831102220678851913806862933608930088214234939592863657356057389753798230483045477128805577544443614274644538349075390387496422787799204789437489548815609160094503703359292652435626160927471625653813976042082163335446028797307854944187, -5675149982857771019989345237321422685203513824901312477247190722954573301107134101264256073204846288635362034298533675945748197102423505883518108509593795807640776710089151568879356616735040353864962867079999026026178197722196384874244951778195261985105316802328688798897365497584811749332971459269011967423371018422557727188675456032543979374694782572935002421953714774480634178222538525031564330017065946687477361, 5223620678782889013526736038960465858508185365240108358218278017490686890799818995234086432702599215048268271251937967034909309701273687327646279174464177439513551850649793719943240843219582542905633392918637356340829279759373275473330009166995049972683395905795749979413796156229426670116012940116568607601644806074357263209318749898479657498742178030796549169371901827737974426207578799640548188009016346913102220, -4522405853469397534857372803407064130938589959085546399237241534745917191854406403285457593183763045451863441102944811817750644247244820443298567934904779582628072058650793464651356338759542032771356622055168555922504380387555409088325428664937785924438777438693594934538073132585183656730303179416716287805822213925120496485646137392834149592359313856701751445192035095218497517458804163224222736989984813005280777, 3686806258292975213240072273331806366121643364051967376441856768727757263167504357850244212962677938692805883386011100424376712285806399199344960916948144514337325908609706043669074346674856598592160379730360992000573505023122348831457806926416976783416563822754558477959397176189866576465837375212427497515916617625161686960271246389520145968972409920697887042551654531949387225046878007056532647410218322153775789, -2831534142142967018886405632138991535707966343838383915245968852212439474477193379284310491217902154569187359784273412057628975290047246483521960160049861921421590436884200903487550719764796004291655822140504208066127189402133574424113684238138155093218497759873787579473136581522552207645435280835091181138677867934680487248031495117404786161940912210022038226861644595370124723946893836339586310972583816030155827, 2048812283860670981730433563550062392281820285571979983305572025026882400568683465829408085234402576519252888686294751402801913362412671480346954173901780450812806518601184499192963857187325043294209497295938987508244062311579203977376486722993189745819765973926822036648931849832811911800926029856836273789383085150337588870736546637995889821609382015062867837755853912626414327942164080530476570696349485636889393, -1396254930368418204613356442380631517714558383620165850858117773593050192654989092381816466561822644066989633786486957158940733092112204362869567340446791389508668487565642567538580843559737378798538704159328490435662090580910699355274068302962003612649234093187649606053857104264787915739681534551092212564733335771731498589061454412608116002294241886758048509341387945945057437726286998122717380966312162874095082, 895698505024367485332781996846095935564653864219876632523070819147001000828332593562431445968934783044052440320169221371453095431651302128769852654379359396644667613347597261363589970365523343658173520298197908735382101702040672355997243433492238829824726310560469533101158005560277167277827447835629951466297549749092029405311848532807470231234892946555218645550162072519781080281697449031512509922867758674268464, -540424559148878274386234637041152840437682976563019745654917889055939983304892285014387816216656419339344959914386091001682911417207446806078177612122988173304235575390463334844157870261452467580255331819884296364703804948023741929267065577729749973484067561677241757097956676672629475384121318589815649121614478237264671416614138918908110346200052857731157715061198358284452772013741152611012302656517666656078704, 306346135682612878035596978539799404624784647896878417112126456512401409616454867478104219397240675967517819350475894646806850013645483982967371367932250776279307033666212012872059238848172951263048733554484567084182381584763652877882023334668694430178482266376141734139470094554063310450960015094951460829667976146921215886326783849920743703116557850021316536490471565709842439592699002484719396313605961863591107, -162925635811117006249879064972097939729306758028037633019004079892035456894647747234270870699537140248847176882468468454315798484950872489683392694064733921688210477460318708473539347575252732504873422423943518119333503010365128449363260185947504797817470632810335018591191745405826728109998669342089111365577366344720760132107201800495824606769586978518596074862831494543249194071007878752051059956237732953719052, 81149189451808702152421894786335968929783964779988239366460789636175703178833481374837577004127665270079128180932149500516275915011046977018137228560869551649152896956342023010916925482717245187464609442025165458308017919016738938009417373987623074403214733639015212531033141265940901304149173881638854835384980798016174698352811195534630742224791670545902614599486665872634578462961120174749090629598064360726708, -37761137187158857588674698900484295735865895859483794622065876687614253723125010650784067913165485496606691466045581362275605649216182275062219677286137453874495558798701119187791693082760370130090105601835060115247964841471976213000667072862882383718870874349134201584860362751702308700002459814131905302030628749978973826958889935929327413582114711129360528610534317180080359369593919149694127578967899975518331, 16359469941797054949452987996675738996258813848339514660688396279266679601476028882654218947002451641443844021657600937210977523803855872710090527514372999996736405540750370586125897937087318857638874953047469689404299234857695451156679045606831760351565777407518261431184443121801896367323524179312150968230332573102504168903962772662506539623719511205613770719935864449301887650319507826721119910640806708351739, -6563595483112619706005876540371903319524993099997552040773606348122251128309414945246794906315967726661441068931425922545439138752362235603852180452077744501304450474106090536277314249151596048710434092415634844709314698072152668790650447439939474758376105960389912569450131407133428200228908729052151223208316099048749805590864635197801898101420914931429855122602544859156430354003980819997634807501509769381721, 2417049271217715638923339801689265920689898687398321355963229321389675691179189411630813362666948364169765328845904363775815199920985816156709291461753793613151325948794285032144049347799457914453487623906183952704627392349619731548489946160481602975414672737758071160308747699308392472369654091353595562506860465278391863529991585298111810154521244827969434626176094802630886703168497035271047167969463452216596, -803616539057697423806229199542288178241346537393038760467947403346171434420388621156438835289335325793749362137584310989523374860821989644325236644325632371141350510926215453267545615333883981332475328188826343800950103166403153579346971681112639600577221266493632089401052329740898830285747714855743411848507704793316768177115412300969692948787476242955531908141706927750319075951882609043058238360167311403592, 233019042484714794372750198328521553925952308655190706649805182816613784057851920832801747871618849369995280379399101815420290559065123216181821435596005178098222243722043040359822691588136124380416147413530293816357647055036098344830064552212699517502311843824435509897922393797777876626425193849164473837965361095982382183756921178828401802738026205888685736868124032404419595725380011135054653270748676606805, -53767756324266623306511276880241276445919821442877200043228930409028572024914904464419535090697936291416472749028395237660668127426745512423766096920860909108374610011073282484875629013741671952665020691724135406242561785255536076875301899991093833989468082937322954143975306935061895537035475414125116069777550186440396658002026708429329653534837999843174888213248777404582866536645763770892434997096974615959, 6384496458187671105920272471955105743386667476381814308422146010670895302252944656273764875735578238248957430704991710794825568373306334479123554714662320110031478624999101378924607573387598230198101196827678340235082939805247346431251065399711425648354441035506053012121554839328871706882740966709302062030050746447471724012418697746302807313144229288616440734911122588152303801819499111494956138014970186459, 2432635643999572395282166708889386234509040484452381430956526042315033742079588181829466689482314014118495522756412575809589318576549168608922439919602795894503574032008009382131976274020474569371500424646336921776159999118951583824906485425573582622538304573301300690937933612408826336999918086795987162856097425430633192281308215405063577720453301279486838224000554910150788401738518735032993843314637655877, -2329274405971719568952291158132575330259978042076204241460612292334885633139191876398789104311965171113193450922157102967621963486676236258072786595305904128725785774109467059251394391420440900133126530068967500101649330842434234940050527382903551960789651394257953930307829342769218232984131556936716502223621497968033444899740460361653146283676524824315450593820117176177306656944693783306691800750968012400, 1190979546639316136206739036062025734032246915217370372873467190063936650425885360218009234506028003688680593663274729874931814958958134982779137464332605046664799212143264572419621268367379815138262976959449591626342244144869127401922922386880996460792853926635572820499629637702835716374849747786074499472582281818056916380189246101112774039642848756497877942934081120429420580511643253404537694870326762651, -478934200666514430334651985817502213098106679586042606198233830286600403098460238416536685696723268928931634250322577642798083389417391058374488145463065464411605588796593155215173130883605940309308327301672411050128796060098497858917831411224185911149773281670637738695441307527709447662959147420112108063207129073157979662220994061680128130893373173402430261121689800115755705775177820921894353828438896996, 164007494616306297785408062241695529511960316033567439790387403323647107155802964080090364991782366269153788255711063373203040965016661884788363631513141066415776775183548896190862500634462470006838802749933825427055663740143612658199840810175028154479810924402644869013338688494570764543785896682068798584737579351003163338768068155527167418070083794155088646852584966444505192543578283515662099505781102950, -49066427293703435771073595730366372117369051353639285308828892875787793957792436194941465234724913270900848586799439966003484816949116574357109267016381440549233635174367008634583888042089549601386138676381938105864897886149087351954815706002319699612246710666041889622088552445083654594707782840828004801148943551373195353617843500371044464552012548207505018716698374372544990007298092597797089533715621736, 12923730301280420737690576671945681026295361264041112319225559346869910587013576935617001458206327304038690527093948951535409448044797521061957155788948700679021462503106095137154819872730206510171873585091554243136964039642371712952775307032707120461417985880790073797541088132123528203713852688028984109668293753524996652828632757403835068929201199967463665885617561335961290467952439474484320362695954770, -2995834099509372531978194886363206174106158976076012589787854680546928134718426125865177031718828889135640362107532900888581078951433032848233489785447267000576983253075277399641002199281107393409235004387787471604055891001950597800087814231077281669642033655939752235092269280866724904837426946837516809996808345494947666404940646899623482913460816882819095365422772204476890318193135630619315187795800775, 608128361355579153451838342818102356237073320682828952484888068273486934038133869720360071360572569555454451020652517917973195633183606132478485724020034861427205963761257748015335871159632984769294927543827092340106022819451613793973973638039750354657310018867750475725565152759023876158805509811481785845951423201150324321280351228371116611917914416303457485673663420004289320344982402099402722345242588, -107185635625747081629555895461365099005987380048246259777329865684354369309482596996555818563237395245147998127727457414734428901106156395013778387865268647737746125962008684368798728682923175487587292934335472008080840840394872744050660209259462906069208857089676019616267579293424219660091785734477365257248102532196036562122231532056260640650185243966001917126313631446501489666642284977305124422252252, 16211247551095283092563012649687005892014581921265303205962981940096904551088331324601212387144270909990457774754070365770549556312397162396879927020866470250056444963862766103984507638254325810533475032296460579138244043271038804383673168792410166881604758591582573753895579168416701388993031720583069900837479172980275053148627462294092709282200040013963991228480353144472570824950845676460237002546379, -2071186193277528862443776104892871695568458238671308782318153767573995339706687077494167428209523735681757949878461163884127887897452284662141366940196425986807780874718453231547173992944161375337814835203670140536521886450470485347178020678875332231656968653195113389889698195048515147664413785172248193692815786277551347020400707834348360373536212021068868401450934119014091764384402074156392508500147, 218901909104048212113219536232361631230275488740090000197955882158569173422974276482966395795033759517321902576010622132353070560451112039855549575352534844240270829623010954969788832474835580675578608120478053260400798512136951912726032979519976257095651326080771859163104854661585918658311829281895846746124381649430167485042166166838619646143823091277796780491831930083288747919744313574447249198370, -18595412923080464918903263984596225150206349489024918699613284484605321543983501341622915323415609930304227415171979069111446690559823241058753762663500857646685522883125334837355281301033996128591010344922194989600500820675139956376270012884989334175107546395535202389708878957634587535810296721229643468765611110226423211753725288840551689867418039107540717565593188925793670734827106403882715519067, 1217797137322730218293902471495120173464124842530405457192404390785958461904343953734001344167954907307428069244733410660510131244176902252124310613364321981578757190064220130359848812858004779327016991070761510982118469538297618988819611474901236757308541548256481100060862117250648370811586384843157537865047827994137154746548889219911710680756311512673566684878731253511248635748075353080044024070, -57572937680015076509021550734011824897214938359699519477608626083033373125062551817589728244159628987833466623842957084291149783862300267106208938530332184515273151398840300767964813339084273885264870143019196707050217229927177852054580433499432459483250290315153853529614187890385313273003356213489478487223794291930770105108010358798756063082887145143228654784440921467870635531027711278942417400, 1743907432908438674855750820926859069576154987917848469557345652929827056524867872301109553614527674558572569818011094593072857994896524247239968007213755731689592767477306446933129516854938549877714020584116011302676647861947589308370701955033248023718521602405946355415737751596380954426894380307975230911502899201642330281891604310848901821620609341363003233189429667579155392559770189638007000, -25333733974752839478658452158966704511925416209913562514558139696115959684173221020294465789066661430542913463664946639739468182749669019409791535085244502129819911660627746207203726990157529559664217237818222509765615411269347422789665050579984700058592466928115645363638943646217094036851976028604309586832534417351383749961677301717974521499174622734391799868233490442077069310498006599850000]], 1], [[107, [-11241392739993394540678499884118384024681963951103411860586772562005827812079913209039425738420127846249632951331864761135633114033533845136128397730817748500809624775815173118338563875233462734942641956501008244920126122648995380381312138163673455666530849818436773663224626003992892361068503818345222163899311321524875117432418172837323295573897128233151642347575952963041722961301868475718276864, 279568999290221780458496206056923776373695798144152693597640507117670959107027423551661901060460091979123942741901856283663708591832186698786586767803122423021404593126081893790863463478217662503770565496151500498786661196462114341908381507832040028929085909260460239241971323726648528737972874518294562507174535511970535077423403314786420272327729235481475628794006018069227785939036081980203028352, -3901992236500534872236689277902251852272712638018058786003351525867582145466662903576616961164826224504291843793519013886165418941583772544248537928639038790156922322183097012289338150448147046870916593711288061133211061443287657220461725649710795901769725032372056698601066144719027189293244455274203905319876977068742084231710607677666930446382127936741234544230306740660022934281017832221443187712, 38868465156937205410109941948335011759202759664620572139836715218488998886886402189723102191347684875301400389207896612836080229456787654309482060894575563345590097290688022118990645049640363559908929500766811572934183253010364147706808819492099171134805957989624566221957735350334477604075384014896360160507787496343901776979391581064401370548316506676564700388182874997523522940924702943326162868224, -305006099162981209639846168064282461566039796939739281365743068317597513013423559034865180635163664268823102738443419592605713529153390388248414955994171863176532061262789233181906128938008928702860394552906670025661193166712930987102977132854684295373520996550840688929845736784272866922962456610658553702093643022161047253916396048119436317135078938408596622142643999583773829509128794274675949526800, 1985417104906533961428334234706306647491677141657877661867113946508620698732227844461353558377700765377107806901374897450198802593115236055765457562889895525288499521463867804957992444854991946534104245341726250871175226711395325903080325702552564985547574081995029788555125591402446266404969721102677620350937746401001592052227285497086228174335042935155647426976734748415627038724905566901635816862088, -11070457690414906771600860847244963006081001630099206535834299880819813076549276648366985707595816714376667976245840184297405092503981202558284032906787029382139718262706801271676335309827490067795332139403386547290750126270475956191409899301315907198231848973297597449405399474328496930845951053650856257647899966188660301206793889296265267198428773755589239835849909261067598071163939416500106177482936, 54037141353384229483607702719406953497951536070236400268357779064627122620480974582973738613785836612193134165747377762247625762204709918865918965907925123993022426104212126158933934322200368503570921037950379842560316784198805117605128841586088254145198035150073084937409435331463284414090182761712884778629652569108263134634269444364926946952871967301318529268805370742702319069456814042470349798674324, -234589575647246417359013356006169884560743545414112557799020728862913172465231669361698307968165876236223775335768647373058114173139698953703316900389028426589731502286465662960367668539880025062606912882046717612994055817907323691400616369405569777665535169129683500193302842736588616045579810386797079122324093376848012238999177967729915336492133967108926864676696331243413602164244369381794277910262952, 916823695076955034530059323856145288724057167569078121769883975635847218026227223056108346592040257900035079000669127837952409180430496286199880990908848265424116811413724743235889587487825026283163096589566114619865290554333463082320239776003464690547196001935936061650220047494827372368971555681740607454576754769376686323375530086267513023011383108199819081647698736281410685445347227381565396856079318, -3257181933206586929479708173775736123063604950507070861733967626749030288060792351161574647725208577525241328261215050389788137348079297317050919943418598861724636579451478588710835045603495734381269030911743623428667969334586505263762813971536270180738249017575266433016481488450148588135208356995639229615174442421061916647909557449995879787433437766954112153464719535630968908520506558932833249838815318, 10604340888476679424452606982410681410647632969706525337097366448976654182366687064639167614873035709038357258961092847764305468774762960368642612310446965208894116653429639214425441113216276078503765097649417561311716267876477659127806921121205690959986930200573408564457277858477159952139172336182936202077898421351476410438548488884304800242033449266547636322867486552717174198766356762898806437904218581, -31858732125396425232261248091382162885686984425212306468035435997862577826061365474098148817814517159729893410165854839408029394534555363694874772947171496890815781903054230670167975117399489162908071643029649817275545463513455242912232121583567245256038835229915780672930256296831248313717820641312496817663596829500613384322497551193504956664982945160049015514700839653218584357446474368454431626420194144, 88872642496674627447920358559982860606472153688965023319883908352371199290593920424721181120476342083068208837151478658031310181083751581876659497013641505459238210117778132335261321798228903543096163568849621852379923293629948697325761866494658557501435686727761718801631354832033987064306442621387742036632858156383340825497399606015076228364468127263836565583958496461941252925865627414383970365061434784, -231529694589084896492075047723670668696440569589961068944605957632521513905510607374995324344654800590800949479158413926288638339885261990579980896348557461815331868881278976494492090305539800094582152903194410405493356852479235466596243277554605773664837605716495661843576719008579917212845359049300161728010159997990410744387860558701143540143723286455214251221296913217449883982420104539220536875847554511, 566500174144002124378503160019025884654683591474645247148606838553618327189530116897908852837926324315281076520906626964914187624499540522843530365840065975280850605400570100904965420968060852521742831976400123048922234841289434036567274681556884205208191366450624707511275873890859776691241294505582933833346264757370225025336684146259142418715324056476487087154799974245525639565221073515824364994383384974, -1309507175883534924323848635290843118308683483568186067031676976454670884873463962026522003669161700951978793520310062618307424407425063705916445963519718716356411304016216860820928065499445069293584756306617682514359852172849675041065125296158920922193409826943451559440499841167106084508384537170098914092164664897894457894033865763491977538855314370876074554710795987906523594866892258857157707484812142118, 2878432213141210907648082067445794621740955238601177308237577684457315709165460991406263877837245930511042261716449579812025218611136304199923636389906540786714843833051498695217124582653441712932372430297309488598609530494858817753665130181413025710713434419178511797770901084248073269898221367236505321042716260855195763952510470079193481124318861777006129181812634070013682161080933832127410995916445399463, -6061490891159644399647228386601004777524222965095446569439459183619350044755275249136928131535083585238902433525789507252632732898450897352084257748274431957026897340079785917699588786297709656872886662511028890332004309340305588950684458359868924024434515953242884741419624042614867364965571251582927903036718660458267731521918239447402564586473998736838076923300067796264687367241751220981866032141193723239, 12333271046606835622204338105200432318530298590439129749618139965253609553150400637934053133178762360512085392638761277018751521963064662389691861845707267185191346752956448615513157743266725413737719461152384670174793654700941541396616956393958772550874547755322786668783201008115967361719321091454924943564780672465849008734549175383665957146778753842062239108512719747268030661724842042283899881555567999356, -24472304238704345280865229578611857783220712953470894392542300967127198722588210095095593638840436243315749508571598037103356314033266010861433132184265559344088099297340317083017636386952676284748538575307423296770279848788950537571528717637026561045775316514933673324563205569844215087419300499041860495521798764131561675889162618877688230729278752755722266722114791895450664595242271329233641171480329723999, 47782238449164305637657359290818678379052849242981646611621554015965372008147929712869704548956135169260943444164855478022810767069293936004002534968540118835249029592444451545241039319180320348156891258350910752624714196232063297451005526188398541867897012013655530264330168539521165216778230164992808952048398377112387621451044713410775933289807711134877287679955265591308986456625792982860154690223342293915, -92446587442309336310246653693890310519032304609239677910441356642912554175139856249218396708128469826370031310507143714075585666598697803537518443977783925984823648149216100520032763560527617190030176349200187612063452971196094492638478947384730472730371265073669531200464205464540179930761566531292994868146682531696222730042809586695938352382406169219665933506442824276303479972503209491438939005294555436321, 177812895617084970546941296727115221843743864371745971968029286524326368082309602684165886073774558654084215310748976742778745899128328338442560984644909841396358042112454466128614543685189114831885470954734594874780270381313812999819884217180828467944752173985217305906745028944107014114744126241251474095642282158200208077110372714887234358135940199491973828772267142076923972564977524088832616832398849205372, -339547057504918319392294805006718693303444824796619397690161397299140885945008870804694913961554634887082219970104459231898760679002611646483576389923078357190137420448283941539516640852993879843856514256476138928631728595839968120083980376558716823215467309233371292149810484263699000521876377831513192610162957095348116991431003531896431142016146937649843178104760884979714986434150638563971647984960840978104, 640280062231670463058829791464922606005736316981314745605235179558792540517876024514911454602147205761255988044764016172129814631309187492131606274063654262127006525104586016963204133550944499181204143577709927208134781121836759582443361387417234982653349320680042428703759691993749046460963872767746909278627094685382428970971768060228646949859411118276977856178994212060570166013055295612798600390312037652361, -1183052364707928121814975719255636130486579783922425566917569304483892463705790973025085586691539397311285564598740195860678973424918387392605685591816598971991159742851188829121890271524368210959693483622462150107051456806999243063733300370002450233621170665062305658662062523604609592944959014800370547850357877198208979824366069429014272202114317842936276473893926128969313982477088081001003913571006121000516, 2123963065873869729265285149272044675238196531664338880561801630132745241522255936567226091229218599752875300259360204294324727097710589967561753337064140056854994296852133803391134610053243675244300556072966803567409741443749270125313232497040984149637605207607410821055466833136822893254235937541666202604455060968461749970564515881368465344129136413092073426310862109401233154623081695778059538783877716096471, -3675730753911257482310867830168408583926887149236539821050990493137377321979730131336424143789058776171084666051359992224642405159784873820671743695088973302935413956453367261137557265449708912199212005950827751681844628851690326499536218615331079167222078825209118944716075451361847389243090934150732789353205528715357538363497274745703424750505491551479726338408510071649024417414432208556170437186151318062410, 6088219422706411259469187871507579629567637628046462509534445164785502210530807915603508222653254364745203886785347812436528540226525078367715161263530283146960589538550064578703073876826142237726144604060935419049052654658785383274121364787534358489884532563071061399222913980237175191358618193361116674715034517131010547833265273464823362326500657464392491072066053448430534851236220721625659553066691960577810, -9588152700020045238216170289047986963601727933452934718068289004750558425056697960938318133599708761783309859455681587132664852694263684715326907215014456905973414286189909735368319847241186155998873296982532338178454053551715738077381586218503501683056912795676611611985307106116231891974136381882694721007266398595339513432909358109912324592144367956528884540910823890516524722868459590459803030871144982111396, 14263459658686273920388979535997594752602122568862514672108446548080169944451784055129305564116768179409253972013789536892220552857688445329894193750765445939680774657512336998124353576115104348408080734131886967622195629434944047536885717356109965665557299315584157107888777455966490376038576249739493989105498635060171056427045501013134534294789622745761484594992191326484979138390216684430677556991300680935570, -19894958615403790322709268020664149083335042002961280254702291644483165973785855131135108579764198723969494960761820732568331889171817927597862107186039776454167120371558499243821848495203474637341511421856466652258075797314363398463732685916413014577238316296391056212103108750800890245662764002062711122585196827549412456240847295517906887713871772616701635539115106433529751171620445279294290458703304242934829, 25775133848895891614429503156593110908326959547834566900438284164314843159433163939591011610980748052870559566686025914598920206816358010816135124913713033806051426547142985894761980771839956764699381774783923153426992365938782323552279442716078078126781428648036372189848206297219987999335193576896869047780197962969620713992594872195574362379445853460816951295362800148342359640220168880521148486349483275290620, -30608993538198124599912257463538119629548926781201256007453088661469018661565033757004641867707453885417132522834784665682768544498591789797817937566801656972559551303512412592459083566738510420676217764728062545980966332706848307053048409589950770945559519238484871767815619903727728060890576482520495690262177106702961468552410066445405387116987428861891387056181608091575430981047461609362314857682870540142897, 32648260926412296372090914279858700654728235457890080615839996028975623738325912006165999579041296362179998994365419736621305277725424916709349658037245092964516739027368806161070622535609862742748535794173668248039693997451262222922034645734507876137134048706828362378693763776481627580536926921849355060575984246778159909294555637375560518841303920058351250693688038806673305142139873501330190193341115061977757, -30228835093715523823254295989381768031475406389848117827365664480352777124443839855715349087142654728754685342362760653455350981452975769896804018786860758540127947333365572165064308141794772845219719630436062329275817192761746863416083460385574530953432636383478285297108530994847447949593322432936348865196293455821559197434557584411382680448968732751651821910775199573490289541618278878928476936080369110956170, 22807560270442574116249597699362159880685672807550693465853870044656497829378731333662634250434963005421166647439607610183355025990412593608747413862568802822908188742387781125780802481746153460122045139372834098438084001736357571398977129972035004375416080323386175404067365933453758134141139802513128356870667449960786031246625920754564820212657043090494898825046266905728477158523995504602393658928055788854711, -12382307874967596079096467095729476579874587633785440773604051937203263813972983700283639151736379835292551721957614508411952962103247462376345238677078014403172017413504601165448449190299594747261778337009062889450996522190010179711938334035761216506892547166142235742890727623879786782260921717091788634340405326457774875525199650773069346866167947267592441168222918890633171247357417748892004103721213180317097, 4841534386845609379967054125076446618414081582195597046631308135149952177899208565878056993600226622814734166670406702233413531101457947838197197257169660767065042534206485048987427282370828056664572574229619101835479104480842861301761538163136338478994418957696351638383446925839419057076280983445139363412515914266760137404717109886377488837995254083593523016134874066077157599437651467755587252704261826173558, -10448066637158861548508479779444259504860840738885010223723651634447825994252803109275805081465054260088075160719709106861017347340807697902591187523816596733780327713565650616174665505252942650413519158045615553658624534716530225091472718909647015602697958091073518176548882571820138641817628720609173240089831451699817457798964984793352680724523132131256636268840133691685528236284646421306084608822611494923170, 42559055616266952760962976704832246068473184903468953314265709703166243787796079834247616330670362845863184756562207087171965217211749417861875938151998632100418001509257450453264485824478900972539743063728469342111465370482287237712791364845017059185231425151179431490153805459205912218246589744646099879415951611047154747487462592992454481613442096586069266954657228230994787841789766823334258281545669270544125, -114095419028025556773791474445826607040969898320766027603728780200460748282763000403185086656146596908509211174858230417081728685901093572324157100752481236545039756087872355569218328644774523726719635469512152596143233204011889771660050492319899561854812133452908942075655181167841320342875001691693727635967316040187042920626010488662281793478626043693585862435785251597044613056501670026142377026612783741736321, 232309782947463903840152744919574823392811332187527831113940319473482863089909253071446330189073246658855569173170911590594852718371422583413589974635920977276711708479611749077620622092675431752459340210550307124073071339413121288274027654086463225892279142305275669933604864952603302575669100008086841097033694930228739071533526760096965496517156180049528158255016466599997892031982684759281656449730327593443051, -393774493646442106739997562428256961879276732149796151790149264902165771747555503085692291559066330482037463104676270054914048523370823193335145228626897417405557354034156790466359181443840888637766691443833884391098405795920315610707863728723645375965525005020650238154380011771927615303746274329446049955377415954276637740446010231406261498757206887012520731857261275341076883946960202543463473674576305713740949, 582454649508263862756402074862611815260016078940742769509548849676488611734390060129149344789352843183297362346790324015109444886449473839333294713187644078255017687506317766590840495005896673236056251991641206180680602646804129005710562049187030130387667113407023854743484896936954288369448664894992880542017163313267857103265920939400191398338865010570082693372126395236879886365135554927534883260428074752382747, -773269123328293023560046749860450072855132213927235845054061384077615974702641167866159881412627168103873598193868039303240993114128053899296218930486949885879764500281941860735251163437442570572471890566777310445173959918428957809204084630796053076363510104732451891565747656650437342156818219996022340591678834027167948128867276288325753230928173474481019434979186547734943076384530754125025482217262893635067549, 941135958749593700723256791911990317970506555990796583566472974939711315666950911125254945984347353524138395613952910796148063210520804148812383767447630382512382699809524768493772809850632077155523404410457036410396761184318447543945708017923103263344215555761698852418082322018526733328268891972331784055843252841959148132857587478874113544813398581755922556491699000693141816245402230194610514692323332447343997, -1071770538691688651417566152956658381304752774488893127016314610051709713170916736600486894924675718496759924195132237103975772830282370630276829092475952122705021688916208060310009796897986717056293554493210548432762332520309672294060868500085578969864463550126588365261839285268498596807925356723340238964036707909894589043905180381631180131818071560270427346677685842442938306603606347447361201180144997402021550, 1167463704550927145183066378123955909266476254284537350378429520789027026771342435732509736603757934586046372640139820216838347375410080159016660383960780095786686066736373352535057757945648667128080608072489683825339540717174724387363019347688605955280399693080982939276854606399023089670721743966742890202268278204275097164337408055571639369954957764021645738189550610408839488689674580882784184187466710006204511, -1241316165949471614468896721189351083054266145036336320450096609165999171741395341421678290623963019923679927489745940297649156605327468311271591528978468492471568793111841510867316171487109032247438451979224804401577124403261775882919779066511659203063560929475024678907949874025384713048010377263740630134853078684760977465347999667492439367035752112599753228379657892831808863660047079623867077329820157243815236, 1298418939792938416507077266148427785767531846451551007832653965182387300200093636227456193304505146824470314200725883072743396310719023717838291328205829406703353307021781465613100895325514963439534443918490034649080809472158440833148149999301309150762901153133839565078846799863089627256532550803465808334333006615280765041136071881339793569163846829206491181224354319555021272757135688619945019106264260057662613, -1310865429641598312019254467971630822875308534444513679783521466128224976687047561181597189862208129186862764481111746290958869360976638333843872549768001514603217991288105106929760780369946575557678925299170302949623939910671503738627901251834647416496115760154864739472790596061389070052455776680528690011068102175614005532521591470229539563578553900466368472441759034453950982343310217374949010133529906161606893, 1200725001820718232288076306477175444920200334010883217634530108668134862674983144176340686020068310363514502806502444867261732567246482092174009670408921825856134230561843910883484226334160467587641874142118449606695603749333484279530971886415353501846249497962968631796556659857812359553086530603401917157205116307965750210106927658330054151023660256651265382949726582064938355506704843950624336007766984064877115, -845569300593512424805030139228133519049833762881712428834249131135982246695836305260259780674475390897021527835381336321545393155180194170777934508377236037860972976783345093361480852522703490637232038309388701434444524642314235843057070832450936565412456848172357651446361653338797516228827183956592999001339650127496496659326002733944574879120844538957767116826483666142220522702210394972503884071579335720913919, 111881167736654836546621819217479764931630515079087282965230782544422915276234915747395519570635660523144562216969910285555473623779542450711529170618350386962920706447387860698075537124692186977914121358700343987112877313791606692819160929007235603218670725462821019029746312058158257157024667378030090700633070397629787020337002879561852082363969156085289899563639788933151962791205781052213725055073460445644115, 1094340342943859373374350974791856152222449922502304120114517156217845131821679261445399612262845100469559189464870956688124046493615098616250784937067108397904897294017162113753005232011501706971530115452372533929188673897521270283142500974671194706172311562588777674774157910995222070122818526721857823154695435636605241778979035310196449580196049977895075534189678521124214477044870801145114313054247608189245685, -2784457459536672553132004973377522071868024433404489718106934426804654775542013803243350272144977728023749990982155264200870592384785204995215353787248179929734904523803369327201499369414883757797317635298998304087869734683922049763666048082691909658775822025436380574038033577614234305218031921628025387136137712320875590049595315728596330310180527609398302259787569803951171928687515701458436519599017543408994238, 4878093746846659353292686850612347194915372684282141758224871867999730196998466662474548155403967162259982620518812834318586627574909329203096986437336849619273548330819518587802121874212667100139791800849405965267150565876844791336478840435856624776177910322266641636300033240186508248246614421707917126617340038023231278829234527739423900486132248515074026264015837878644106926944726763821694819751099517260469659, -7239737696606060453271469776966101936270821208597039030388830777337368157958184723541530754244149937750201678556030759620863040571899230938671124517734615574553052790442834562576129264613883611746807998676275357549580441308909538525178153357082721089093704063808938654346581977048423826288683409638917239515052835640035888834099978964451528180726682988091251492558378187228981883591663300018885974382920022845918904, 9746809430580330585117386777823707100988414883173856941227205115142912852378755535327690185954567430590337549606419394254459904196698082063711069119437519124948618311287008099961640983927579118129170502787816812264441556909480125686718641431104207952796392611055541728285843128455269990779197331045501478645274408413729238735622809053512743380805843856165493440527710422658413484013095823679057466138401157774558949, -12352427313397108261765943345030564124233546522807234465452948487365731890740138184290980192604780538528944053065119336009079311673483009812156133325981345346912493413203783775235524392287611034823897088135820516628764684550720659011392268397537116851538938074898785981837223971780758917056979281933869005697307112225879066693917205820182403581778173689865937758772465409916575684463769884961413266630877996718211190, 15102244538868272551941898859526657752698719086491811587626967628287715133901030696007034306289871409587615983942030214304821035774550859285651552829897685592155229847876514702583567521246428701417691287613932340422544945290367889734304273131487007322065999089329339296019454051323162853042930401083208400088038474877475932994851892461241396121465095796012016407761373989988637724987776668343226743348069320562683442, -18085422705206123055172088059454309221322163543717133304276549700507066424942858742973979218983261646160964571145153236435257378216215790515512759706860363652771001721919300018765332215492352655187406144832433713499587994093698562171851141194897593405441624487454870353548975838756482022715722798338029578850961604402835951772451478391667630315339191817070543257395933150548179269463945527853005099008677453957327228, 21336158479187569807178853090050999948672182988018553869909503728270146779984525607852249818866829368939022630655142827122009558067943564968836522992756833475349494602310323598338456020699024322168569593444043043872776609834592102437864706141083163709552844409425691391216518424419620821858491648295692102034860554289424171455634827624933918341734738713916395626992726464992182524536155846303825979207677410173115097, -24734183120161566909285532332151616715328350000492636728194692129303284664079609500882892481187409607951502320543479476451581906994173199385216872156344622796261391415035967994471202677223250625370129946377504024798797764127153495440281652630973999515580797792369968670346489361186897523376167917611501860261304066025688080970487375918700764921572473600051384540174423150339991998854540425983459753846317015457448296, 27960748307275237908161263462317858337876878822547630195248926537090919039275880305076528282663258198081107196669079190105707950339207098947970441445099680804688210491739191521801303179445464362114001171403717578912485576119775715900831699637356099565180422475312552736488799410558849647088750026515520571972144593143686244790447635131349364514262047060923725015665970306848255460225348331484305608166870029090638212, -30543952706224390606828677026473537131184232134601928944728447658377312392418060265757501928444947197852305862666492294400805085901596559868579204381346989191072459371547894279992937319380433136356340465862590641152808630228279325412481032539457642046947823254777359866828031096110805145710120584901806584568980713619319290324815948743210098541987779971121733219463793681810305375455800414375026735917798722227495215, 31984685248650673623703113609722620089622353283327993906346361474207228456394951481478590398872219313348156309375337692601707386415573102133238095892656577718614962166549134457643410651526962131145607821095396096859547997132246174774752863299261666580053598232038489441906153221536447401854590274933563853959392766393617051299173452499732617969344851314906675740071838823328635749225338154827866043045530967258997222, -31914534833856702702153750584292413957873917889358525773433825704615404768602675153366198732306856958336190594043797315396098275614760501466545484911806043350131227151850173370097264623081310164300834140900304255072608305255392683140502605732656779618119992932673868724628882098737386267359099678719194969037680437700809816275844604032195534685199852645133456575737055093525744708215374208193438311694590694149345753, 30220852550217144893602674748648478498921109579728758631411540164710195722411375878590271033339977577616281785297641969733353498463131440343037041214935077772140121985341020263522843945233538275647465826954693103243334573760965988258740530125080098220741737463313513825898008852452088318924225058353951463826035957300723715041827427831434125445768709865947674217359620299521322559802754804431733566804259248361418587, -27089339416848280162655375405700698542868046456063521674490016705492121830624995483134758139962426174072010278516982058100616109561801196267839305616082974797645782047615920278498827458746308217435590858756544796516736296641158190647660295771810656060183983478927493357003944020039051945074250815012369083987792184877302660780947261955677201031824299250327955203898208953064047874050140730935035820003863282414845847, 22951630913770534389442439409160693858792360430285476857543450379302206691453142391365310038985346057840257113218036450701420889358595085096974447273680525211520754697562018282552423832099992112133901951342494604583404682314689553926060078803606703070205523440434165110224575490494041844066810916211299968113527234941858412240962683194571352806528928207178560855841069596679876479940591062776398418999033352520221289, -18364497021156161179996695951143429486852322929364936562107566373451617175344703009281087707540290227642462085993323644776045685933083540376155666931864968008593084096269805863784875425064025688085488874647287235303419729515115943749360745478694812796135889733065029332899649308364540923787860085833905709447005640025199328381009604501306754932902706169760613850892435985756670353554460792436952715272948967567424191, 13869996028355535099603121786902480240584076344208218179124118071920097871797926572936648391642695581578618729187008301615474463636972256445522001548975106140625949290756129038823360125820587073191098864174637125250936105762242430256212347193286401241760115150212151142876132564492856467782764368742099788933797200465828479252538354373189793223504046368185670229683573520580093501166877403633393727728152597573735447, -9884574369023112595001717746475041162922745020271968038810352239660150998315765631213773807976313029080627014081319843916193546889967350671429164502894931464433790834014236243513399517759434037040747207108655620153105697821186144841389137423954472155607578472374597149664298928616900493026035139608313618264426646294964107411280280694889178088982003670370227570484313504762070290391321430411792437812081066578629561, 6644913123696235397474453332410409328175236233396468360132471538811256075968029002601688374246582875281715613108111686998111369624110529181542130116078465240698379059096667765876651074913568452192645873506996512151853518292685877586875732102510799983353876146639262392634214224996297599346079777425798521468824272488206868389525275960028515236947412309452305494941086807551523051745485727602143162699810544202153635, -4212135313199327523061091945761493574477504215071767217625486546705781870206497149749792261309696524526390943173101361172903270734973388025022881876434183755382688407786260347641609548337671048510701075421225065590599042503341183385541706421907549269515207945242096066154272876634308506623218821751496819894288638947997893910053010201933840728812933444892825202734954612776524981844549421111813034182516005632513229, 2516220358489158170814667991379146995916948548238429463194884572622054605818845042313081168265968732056435694799329603443971114303614369378426382117867358694260909755464132515892411555011887166216704336581808001727150469794265337225044352628559734542835512023835040190213398510430234036799001688188180858368453912266252735397771793631698764062023598531777012949152569207163613626235662504701283012575688730969955528, -1415266252453313457380806940569389902421975019907237318556797967136494803252405182597929347272786855445711878818050409820863881004983751166278142022138684498002698447936692319241325263522286298924400750545701533170834656865951184205412614737029710779072326701057523246240452378833906120987223451709949039477958747608014779960595395231509001679570233041873853781582971315665571379831481428697295462387127964321343686, 748417333184220101854071692495670166265446813527997774642688367606343255617366245987156919005640724994344470622890169615530927406551338103182035968294434264211081304090924525635668739024268208212423555728980737745781030935022844931740075348990523227921204713384122892797633882428516012166665913647209973349410037510564325684649624632487629866613603116501936636302958388504500461264967232405107253786511662356911293, -371232049696952440114617684861876736100490298385025793927267028546578252045661908246522236390474114953803653147443920439611374517625249849361460447725591051096132666044161414163608356134386124161720521978501925835494103936952014977122168926326536206954849950439083645739122414499099234030063304966159721068399229003251548041509475233429140770104683492616245883753213506687151917162864421895501126497332877282011037, 172051756721440076665677691828982871016071134675137126604786429786594548223213468657709146873458485213967159236244095139232466520523959859573775428170234723186544243749239370196884911536235408081230361914381476642039949601662500690020778618264374773021336335926069801366488271726855492413291062283692706973311466143417044179470106698892926592349573802074648497692815339608752481985287986676300796413654371607381944, -74019282853208547363627542705036523818055299043595582127704866941362794702618119209206109717284598052572328035822194923275144988825983074228589368502555366842673108635124154183655586646365736775424165109604289153201249805998511842370291347441455516312405450568789093509789755949426218747307390004037072751556961745353383673151606208184106397527617404615298977997024982516388204659564126891527651014560359014926990, 29223020319563050392971486780171191699252945139024634093074359560137494870726163491337503686257054165567781553000750728865926216463272451027975976030148216249324755994536372495811141329278197312327815898413911188684063577236742755627037313166683783757677468628522540212712051979914852511488965471620944435217950337404606899377332385214538202047913618180642708651169657273533303289352890010436933863673498611999802, -10361459843119833134141451479161890983130070002536641450503413467097412319977984387350854914945759967739721495123276521155359339225653420277354949794688416656473718409226006724526765560154232106033127329758724501866604991456485628491706833952413324644009884621204447029153524688460354453980192060169413126525913169012506221936304460214501586479568303932954251181722983279878187509392743522341316793287807211268609, 3148606070273341986375185104590257276452277469044333484082763237026734565703151744431964910604996600427804848312898688650643416007035356956694993619160876229578302309618121007254025405001654856989292997260900019863832676327117682752989324830063270723701388279448870133967822432255256738450990907282687343557223886766686852187722506208904503963496748607043796056979337070256490675414349128355158459056825231338245, -715876189584022337905072164663918534733038525307787592417890038185069345759699498878001560033139548489276526394144874105989403222761157693613948930738303715687721152294279557765079364527429640839644708167104732160503270992225100031061267508254719314438254454572693658170342189043746041766875507919513005551561584972665019100242842957067148300120698732509143780901846059614013621004422116364623812051872947284208, 41648062736084999105102564242255192011757177658226047653094989338229038007818541595853112983075272194634707433225382548091225293461113472274365726103743432244851850374376825468887291941371369941843547251842981270950475322106950240630106367559316483471257878281182713261121213775976547031018977535714200139157709359837561648652357225936562026818960833333244922559074792683537240606747054684736274141073282363036, 76328366784821945056654995754219579339594887600204129793748356334737496987535499849991697857752868589587639058712315632114724549943728432209869519382843012397898641477317124556615493038438066323731475240112953208894617177358937808885918359400678972588813577254565039860596890659230162777642035938898792582580922091820166452230902036250358722460018396880197382905694745140820615885617128213908303760018153986323, -59606283801936392691622349020737508960459206649141436804165887566979106165342373801291131135716998300905615408136576642520440801240635236567603023986612470227576975882685661564812059537768282339733299471061310184017805432443781809999773891297412000649456786372662727260397358666459030372532079652934681105706338537741461343881415036506045917666812539844230500326859866786130157585722147307417702558538541062289, 30516710711861446926353592831483991591762365945722773393430833897505908686794143535611434333079567086857930516144210123352197646201452280259673862801376807860456400191871295310838981022309149089201841276008697102391804885411407939200605369898399960267751274347918094328037686780604367978507958478504715351879185055591314448505488502419673112545686148580622653838369573836482820547054618177919302505972116046098, -12712801905997535855617075222527363521821213528416370914775887819962242335576863591238273469499947597793391781852168711422650313277982659816442849588357239418366602300041712652161590922959609267707358218273378285937402573938787603621963065423344339158994543146898461572104261016566754732925692176526102934339092497731082591103478010799049511134383782892541373358523832640994586314166874068310770978044819281977, 4561263817917593937162096092942476919676908459829170692845642000812761240493836028001131545168979483306519841247135660994359350920506679596134628369896342087422646930383146699826062986370096612245185920561030091828810827696337890358710814752749089926900346009578941010793738761780804501167613792302072357709748274458042153144809593456264373043016994099056125443733561544721056884627943357581734150499010614560, -1438488678734308322132527368322979361378893100714480555350023390735710387132859092712929448986190415100882662857626683071036582513782761066606680768645997850288869410023958300334420091676246567413876801904485800652783340710885327958073019180898288731684377353092712127200953613156058739466472189599667511511780534166613695015482576605988115252620777435947483892878750442399001960163492057390946381724487509296, 401526503465786432490563923895907690833062877226349278019364345615866793610090939913850970879288119377514026344509859017358615588727227568957794794005497066919458000845176075830118304874620116609524021271973553787818622179669673621754723196912090815967920774665568147927971049593480137803384797369441207266035798992703958513037038090988189213127083837740896563796110786326244477668156489025780287201529058873, -99245125176085862314905078316015809685069057157884154714192390712916790018262915300039125678456705525411108378309662598464792274186407131978153592306517614631543872737127423067642734359048896631333649976851856452326409879449728138571577947039777525117858096312891841260705181084597480940023876835269122979525391227678028353226802380088695028520936735560655534525576176499945182096031668762372032267815818417, 21647039091052621315645330355748609024866779043457494784205798433896994535806795696788644566583586785950150284678677653148866322102813247310322776616386113705247251895471770359443862276468846866990815873273079413243451569534703407145758991198427772848878667779265566651599698341979954255392882910275966943878053066629735569990222464205646536170857236335132329936696539872690833398662335869105972046792733329, -4140138284549870819950209115015550981620780951189430498887128876694348721219634570243444099946489394141440312752001496982098352118466059291903386236024402996902792878510266138588342036894845420521586911663862087449210223929480880996764768328478289689243713975107708963483617289925248276997114784675697189500861350967338436005271236460519835258223917790606084217668242528411347619815316255096143855090708534, 688029119736175800777991126607303559742822465879084578272183146700998627123172878709130176854592117939603403358514357703505124822625814736251034682980521849644903820924122710694923642110640452674874923484532423131822626201786989052956231609716240041127626388759430658213069359097009748040586972440744175973905077741425129831072408528427028158056362188200360057237821069879862017019553266961419634997772231, -98155538395519723757037220281081732606299014410225832068393595012630486384610373982048188090520324541288407604372323787113343796352551558913628291637688227444500994013151954898449584448982360635021860319553168640909400306203248047374083451363879417118696874766821277750557353509789186058255477043353620156561562252605070805742507290460918423803100376336796193829151705157339985715759893754236715219962746, 11831424341743134755365200879863708695366661369277277863988265268531918152559920861376121547250030676228737251711386085799552951811340962605347850294803325320708388873100323438811219538146621890637154250005745816839231961365649547931086025211323722367189525014477449966214327197712782921401620379036903259689290717901494357822532942325167987160661203197127541983389288288263693264254876702623766243025115, -1179784500084793188217171890430398611758649966894413440888550366889506482445215578035508374293114502173452171420510726480887375879212376279907310693421023344912202648589643425831592592672826784004479660441504974143079428543507676973133818887478024367422541254395379288587544275251854646125600694317750255482005228440601459236920407090347084505323096816636271847301921074594460630513900818449283524265945, 94543155729235671020742221629305182089732305164577567961048217848507749815636758230456151315891433667489140057869858571018801733399292392337758491114465784483279324074125146996035237791790100131059488382044503192632804759191028824908581819322694857326821761853859693555642382821833679657289822487359076713110151904225229958578968955727666956945179655647686747713904093642441714820297094491369392289130, -5838739850614575278216089560975981300657370100754945250113982976154801157016326284016671331473775978749056588159204435690395788934058521105157666049826318036975469428950891984397684616150677537854536385747016605226131101412028858443298800349838224814140080732489201422473760879274384500049526070585229467295161912472312635986837331522037524316583767577497356769671114917388226799366622450387521895980, 260159852569482285058744516756614496168353666069754831806408544960867557368239896172188546852009628380504573421397773239206336166467091655160641014313378191677824667631539404587144670785757340187937176218222573503250935793809325235959963062467001293169820792290414953282850371610082080180298941062642379492232717057025510787427615191518597219626742247410685466372918616687404642042951341718691928000, -7421539789529453357386028140081153454946266982113523360867307525190512397754338383563052633773755558640892402246021917714286056835639504887730429861264721154382186725907915026155909269440021541526632607970157344807410353823731561124498202046507800231422581642677564913785478399253774755280488287334045222493973693563569432618490135550535611342168877797459517498864050695897005136994981675888934000, 101442538307473368486813608968989214496216431705190225990469279288087036787062389512524474834902251177409011938899200522379902897004460349577280156180848684935233798185451557122596382671396740745943198145935391990775087546701135229537463927483609374177851567272987586421407898459763173685396004068173776506837263877633617016810558664853412024971171163062593143831352650461684965952198282287880000]], 3] ]]]]]: msolve-0.6.5/output_files/eco11-31.res000066400000000000000000002041311456710632100174230ustar00rootroot00000000000000[0, [1073741827, 12, 512, ['x0', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9', 'x10', 'A'], [1,8,27,64,125,216,343,512,729,1000,1331,1], [1, [[512, [424283663, 42729078, 936564060, 835883504, 519801648, 153230999, 412829805, 778067223, 187789135, 329982181, 720739074, 693953395, 599358665, 1007093414, 104957748, 173576343, 375741938, 291758854, 276784044, 107144997, 234921517, 214715841, 675319479, 1054556204, 411493725, 954066382, 328732920, 345954112, 240787551, 588164036, 420503770, 454912519, 706247589, 1004226155, 971042647, 984501138, 632222320, 452185806, 942071936, 1036270607, 395034653, 436996827, 1024554927, 761569288, 81544015, 503928336, 564898841, 880427893, 897464474, 324249542, 691531198, 410101336, 570361835, 187601138, 807030453, 689235592, 518233303, 185217732, 205107578, 638980857, 100568993, 402954964, 152234775, 874569469, 537755143, 420107011, 1028185248, 910224844, 180977515, 682262433, 179933936, 113275723, 190426610, 1010716826, 351744908, 60517632, 1021101954, 573298909, 630779435, 163832687, 641621277, 314855463, 662852904, 629798645, 715350615, 140137783, 725875865, 897605072, 614413047, 234020602, 528672076, 334709269, 691135008, 352122466, 524449366, 1028696113, 504330226, 254781593, 513421111, 578483771, 114860732, 477546472, 203952125, 764432575, 730175148, 304668442, 589710854, 35219637, 971777736, 774662272, 543424300, 39399066, 767318716, 862780752, 697057031, 773316961, 409313109, 858791901, 498666494, 52862861, 107743971, 924797931, 847900295, 408537231, 312065478, 177079970, 552014854, 624887636, 326180238, 630261753, 370546123, 740204351, 742706397, 317800163, 26620904, 482734917, 1014029855, 469864426, 400816727, 775281387, 276860152, 641771631, 287737826, 306258422, 450759553, 874117032, 28366526, 88649332, 861722550, 743842378, 762742733, 542225293, 970024549, 704372774, 872856832, 75169901, 547429313, 873064238, 390484512, 508704543, 23382015, 85910391, 425590706, 1014605801, 310659284, 368394668, 207479879, 445085370, 908332267, 869277895, 694109141, 51237589, 913714968, 237090131, 960674615, 676090041, 762454612, 720788253, 691319487, 349997334, 588222284, 202230700, 586268299, 377000243, 146078175, 630209532, 91118043, 277891945, 48146112, 146227980, 514759480, 684222032, 1034182413, 203015468, 767684523, 575639402, 115768187, 1010259735, 727458832, 876422254, 655697661, 246224276, 660577239, 211399802, 297240628, 332789973, 103513279, 821968933, 1024158316, 554145777, 448883869, 471673907, 104032153, 161643254, 449626798, 1071982422, 537750212, 956937795, 610097762, 558605151, 1067926484, 802666907, 951635879, 629508056, 963230116, 905996800, 698898475, 667203681, 906465291, 133915141, 19757717, 663490179, 628061042, 801523241, 496889307, 858546668, 201158401, 426695642, 490598891, 613127706, 209967778, 394738077, 948501937, 928977665, 686756312, 797018225, 11164416, 421875708, 114992383, 262708797, 180000370, 626933571, 661282623, 946179422, 6421635, 742335862, 399205512, 838329205, 573698692, 729259213, 697142040, 213694386, 702817109, 438972271, 326103512, 168592033, 349774023, 28532182, 990292641, 378793024, 124607512, 121179370, 232090614, 470862573, 476968520, 910086823, 959625680, 772250150, 1030246458, 659232010, 940343527, 650912886, 123164122, 121324177, 195865589, 382062971, 318101737, 194242161, 236817480, 1027739292, 1040709275, 216227338, 163936821, 41943602, 1073629221, 37760162, 1000585711, 108364984, 165803642, 291916473, 640302395, 72541650, 196920383, 361938862, 7160366, 65287615, 914352218, 122842953, 208214535, 1004708630, 280402270, 582956854, 711328003, 214972902, 547762158, 65833401, 809723322, 10314835, 1065641427, 521658648, 597205869, 667704608, 555209068, 495505477, 988365523, 950245773, 482549615, 1054552724, 528073798, 832573492, 314538445, 32566694, 991801437, 958769422, 933935292, 235543279, 629864529, 638386296, 306223679, 499197091, 933423860, 741588157, 580546888, 990782818, 399991467, 791180410, 405416211, 41256111, 12267356, 753811095, 454426291, 933253174, 618481711, 975525833, 337259158, 1036001925, 806421510, 949907058, 282879521, 107938918, 770933790, 200865421, 500828059, 238159790, 954205559, 154677585, 607909342, 138366336, 456692442, 364992117, 819047642, 302947858, 520243511, 500059368, 784598327, 296966192, 499194890, 602791857, 911072159, 640476352, 638379540, 258919460, 500354843, 480268134, 1044939014, 939589360, 865266161, 690957720, 22187484, 97384164, 143390699, 228972772, 370446908, 470899756, 39881157, 69584682, 817114310, 746469009, 241981167, 531569507, 619356691, 455143841, 58975935, 1016656183, 225430562, 844187325, 1046062816, 613289936, 992346483, 963414971, 840332991, 994235762, 164017192, 88709213, 399055970, 234602836, 578380291, 955163882, 664945277, 518788322, 155576506, 13510589, 643686901, 318977817, 592745834, 798094428, 671629832, 1045549131, 296196595, 450955598, 24794666, 288042188, 492364834, 346361851, 614960512, 1058710621, 686699622, 191717331, 495932723, 965020245, 844209533, 1049837591, 140339657, 967454766, 505904204, 1050464285, 675056897, 521088108, 83772000, 326780739, 326736443, 143323501, 480483917, 828207850, 830485950, 572250207, 220371530, 464777904, 743614799, 127812365, 703581324, 17988593, 443654222, 252802475, 856841214, 815769537, 144145938, 719764303, 759096397, 671703785, 36383910, 1049750456, 126259907, 784776816, 287930308, 183760864, 1069361960, 821154138, 246811398, 235051895, 287063443, 377585767, 939708224, 124107578, 439018998, 703803586, 620437969, 322438051, 46959386, 1067947710, 251836708, 1057098776, 692258556, 253839650, 973154101, 127596297, 586017350, 722960512, 176521505, 528816082, 921484373, 611970273, 645984033, 355355654, 655170845, 152518272, 915351111, 584981066, 686046642, 626083505, 718469399, 536790509, 1]], [0, [1]], [ [[511, [966402969, 485068469, 41089870, 759519898, 983261374, 1051192504, 129058868, 915428098, 867812880, 577949065, 840439112, 128003470, 803146744, 183033078, 580891711, 191704787, 592273620, 1004298873, 806088624, 49177199, 558504638, 579823120, 828383884, 1010380825, 883975927, 21959856, 956243931, 49458068, 583684168, 600530589, 488247882, 766054376, 410788609, 99104540, 27902717, 845914412, 135186268, 848066237, 658387710, 326557733, 52283452, 65489085, 611028292, 154800362, 514565955, 814128024, 282054152, 223213056, 815320121, 100615866, 235576099, 465391159, 316626075, 19785584, 1065136543, 920425649, 519800843, 115200945, 122468213, 604966030, 1050607689, 1019465649, 884485434, 117190978, 1057047846, 966571576, 566064911, 954620967, 367092963, 615184715, 22591641, 711052603, 6493213, 965906049, 104569477, 679517408, 407603124, 341620398, 557691698, 293897490, 603291429, 469096487, 870031579, 776627654, 377950346, 617580325, 109424068, 75966651, 954441951, 524881348, 830374961, 875836037, 1047169619, 930721861, 286268518, 106844673, 287946222, 487270128, 859967480, 266248510, 399011498, 800526114, 1067835822, 14385601, 468752297, 35438534, 487113908, 714544337, 512924988, 1047127023, 168890067, 700478848, 391572757, 472181443, 309541031, 164405167, 438627983, 119980963, 632677119, 413744736, 1044369427, 420217233, 739037224, 185339274, 84346723, 223286156, 398565829, 763266150, 808938463, 805461831, 444963991, 776923024, 219489198, 678056709, 609105047, 1069886211, 640695066, 354319022, 1058862995, 158327226, 474081515, 917880887, 340031066, 636555029, 978935017, 158482841, 222945086, 257590372, 144961988, 413754693, 462563459, 253383206, 564291906, 652932259, 84325889, 240899847, 546981188, 977971449, 896563224, 109975404, 932383739, 69124230, 281606621, 764467834, 14522861, 461810287, 702061118, 440465003, 107495367, 275476728, 1058146982, 119409881, 1071468403, 791214998, 276515640, 1026986999, 880144629, 240712152, 1028296397, 427637193, 34043701, 817274492, 1004158470, 542561384, 1055784902, 593725288, 1060705091, 29255436, 617375550, 19051348, 209038356, 239965278, 87036825, 34348406, 532712159, 85565167, 865784889, 199512261, 182776834, 852679177, 604063134, 376353309, 25491949, 877244750, 962473140, 246066548, 34498853, 824174977, 349711275, 904287383, 657046054, 430951927, 830425403, 676420191, 269907822, 929702369, 510023749, 1073372758, 490616243, 109595101, 112856987, 600064226, 950609929, 193753294, 841123758, 961264924, 566986970, 326941021, 41215701, 601726594, 685269499, 506989318, 996713293, 94570349, 327464182, 920483461, 825270223, 365205778, 637591991, 204164666, 371303077, 375731612, 151421851, 193227699, 471002617, 6312856, 12988610, 515954753, 35811598, 371004528, 398291810, 743528413, 993186881, 477833654, 253852696, 511748964, 805234666, 203731350, 644581332, 965887609, 262494891, 487856956, 1057022922, 298339501, 117876804, 238349871, 666098549, 1066713563, 844265770, 57838126, 869205383, 662391195, 545783145, 72690419, 651083533, 618102783, 1017193055, 86869198, 504624338, 394298554, 275035404, 737508891, 167196862, 577999256, 482873085, 1050227326, 1000906781, 149298596, 13924885, 97775514, 33134843, 490682690, 216508351, 698797941, 493985174, 750151734, 106718513, 476740983, 408387442, 272741978, 26045428, 684801875, 829682782, 1066363989, 927508185, 1043733194, 482396316, 158741596, 169315987, 172758058, 444038990, 661457452, 659235496, 958601796, 1042881202, 889106197, 462189551, 203532470, 298008013, 579948309, 149614580, 942207583, 90508795, 389600507, 1067184504, 805815105, 128605529, 862276311, 508421697, 11352942, 507027078, 874510193, 58846056, 439442815, 459354658, 103811886, 839281620, 640419226, 217490354, 564815039, 403187317, 473032637, 974054210, 111016941, 683437603, 399673874, 334442913, 831870785, 625929670, 898504441, 894557797, 619601419, 821766353, 871215794, 677672898, 638186254, 814803852, 212251902, 303261776, 315770604, 1037434489, 784073200, 775244987, 541566819, 623345207, 739845545, 720537939, 582403237, 77415500, 245604972, 323233176, 748539672, 406657351, 418438393, 175355294, 563724753, 1061080612, 310660222, 179262202, 290647036, 82118265, 949025190, 748178530, 402275381, 7003221, 964332061, 214694489, 748412889, 969307435, 985801094, 423666116, 760600408, 844649596, 68040689, 455030568, 413514510, 685846688, 531842481, 783120872, 901531177, 497284038, 426041057, 699592992, 448742864, 460674529, 506852569, 646811970, 6555676, 869282207, 986198586, 970218987, 238222932, 941658470, 314286756, 432039196, 293657764, 142051285, 20515603, 412173784, 1047405910, 621040168, 743632617, 994805400, 114905831, 998298361, 384755459, 331236853, 961864271, 945888418, 668521880, 467596026, 584256120, 848552632, 838922441, 16353439, 1015283667, 422055369, 677099190, 239359059, 457482925, 974009005, 482951468, 341894981, 4971333, 766971365, 816841533, 316423196, 176429724, 1034472520, 979840396, 690401983, 664743620, 62198844, 692160209, 245552000, 168547591, 911343541, 651722231, 366645846, 1300409, 757267365, 1047700463, 478891197, 385291750, 549328104, 931724899, 907700357, 689072803, 969958106, 141659735, 400322221, 542708566, 225441988, 575095360, 79629075, 794939308, 727106630, 385782842, 668378346, 1023050275, 44047700, 758018109, 635867878, 1028962226, 732352911, 745417387, 815945406, 717592064, 587904860, 196846115, 945928700, 297861051, 381335917, 725758955, 416284590, 254427587, 56465711, 73508015, 816288096, 721293285, 694816001, 182114914, 130303321, 301555932, 290750879, 853747708, 257395474, 1027039086, 499855957, 58597087, 993441097, 174034864]]], [[511, [333135678, 519639382, 72976253, 711125540, 690924048, 185298705, 793654563, 733785171, 188432555, 646355144, 887981596, 553541215, 9427659, 52942574, 470928090, 359609582, 553425991, 323930067, 759605519, 613457687, 194134353, 632846814, 686814568, 225495576, 510573498, 1069113111, 912343386, 440999140, 412543554, 582241212, 527672378, 896538531, 868188317, 1031294222, 284518270, 547264935, 838822683, 164875059, 7198752, 954057198, 329323396, 876364281, 343207835, 323930694, 238044747, 219327078, 790533751, 1066433058, 57380401, 899000295, 795827334, 158103103, 355960127, 351665765, 46391902, 937460904, 530519242, 186981842, 918642110, 462467593, 1003622136, 369093088, 1051889913, 910552585, 631847015, 301618060, 619529327, 485973974, 333223045, 828150500, 1002523417, 878412023, 342859429, 878598132, 33632560, 414374934, 311591544, 753483353, 603510169, 660472112, 408432013, 226244120, 993667430, 190665440, 968168227, 85782732, 542102568, 2807588, 490166215, 1035426294, 622009030, 534646620, 102455221, 993531545, 81111334, 932666272, 106647629, 304217739, 957018863, 283201645, 234250849, 325706152, 941995011, 808611902, 786611491, 206502569, 259874410, 243054651, 224496820, 888047223, 500984747, 618305169, 543544657, 852849793, 98069992, 685467208, 191771840, 612835637, 900941452, 367537565, 1050719769, 431806115, 771861097, 509108762, 891380505, 375833899, 865135676, 272139671, 299414494, 84382845, 182491572, 907718954, 40857204, 392811927, 694135659, 820872686, 988526800, 847687317, 615094946, 141972029, 8379192, 991095730, 975950843, 808230746, 348403031, 556672975, 386935726, 87027856, 170382795, 109727048, 925091364, 986104319, 734173621, 689215437, 44674215, 639954379, 947706109, 104506542, 360983627, 82706329, 103497285, 8608239, 964200397, 291311426, 169412982, 511381297, 828682695, 642097014, 21775203, 204969571, 598594372, 93154834, 284231798, 368970304, 38618512, 761320837, 652591521, 344714772, 950411530, 393349632, 781273019, 1013146703, 217875267, 828965856, 169383516, 24413938, 853721141, 1046760808, 1046288957, 969225439, 284148508, 107815051, 403248798, 499693671, 131839672, 335200415, 546459524, 593011086, 698061665, 653926500, 206782084, 689836106, 336427579, 821301297, 142413122, 882557773, 222937837, 495014584, 936167545, 169288111, 37770947, 35695228, 997775646, 1018885834, 818587036, 665682720, 32037796, 296993467, 1014758580, 808198104, 809861431, 582159232, 749850448, 421215827, 919871722, 987771012, 693097737, 617704033, 237599820, 437948100, 1032024005, 934817512, 1025703628, 242148321, 1041194208, 271855325, 443655430, 130742667, 687405066, 213764691, 975398375, 403491564, 271617200, 989967090, 366748736, 295552070, 339385634, 36004502, 774835103, 1014089663, 1018040141, 841600926, 461297802, 586498117, 234488612, 747755374, 702800515, 103743532, 704579097, 788126150, 427749323, 665534538, 1044415083, 932433858, 904803926, 872085091, 764044586, 198489264, 464768061, 622701713, 268255070, 129464621, 181705363, 346068076, 403104307, 272228514, 504501201, 361551077, 1057462034, 994489682, 653682565, 518194268, 616378894, 98295017, 797917501, 1069441500, 81406567, 581863881, 783101011, 307180086, 542912417, 863793963, 418536900, 152674707, 411794171, 608084535, 503091517, 971183655, 767664574, 502658538, 980180539, 65060677, 678347572, 20774188, 403523355, 943594078, 373372420, 98422845, 913363481, 355996906, 939385216, 32224191, 267017412, 158924125, 616110503, 553408299, 857028759, 546868633, 3556957, 257357074, 865368279, 642569211, 650829714, 856128820, 567099733, 198940460, 759509581, 11350412, 490236268, 5320799, 674185446, 893342818, 331672055, 394108500, 934265572, 634555044, 548781171, 439105550, 328661678, 1050223486, 998592739, 994151188, 344528141, 639544755, 319095007, 900794345, 1060779772, 448726958, 474775552, 1029215230, 319790781, 256637798, 401948975, 3706506, 376310321, 695863954, 584396967, 1043505960, 303537149, 803566766, 938990680, 855229219, 132812250, 893002027, 769993298, 615529267, 215761280, 750642217, 436532874, 639572829, 725060658, 728974500, 222797139, 443661695, 148076900, 307438796, 760908664, 1057658057, 1000584962, 70403532, 570869221, 59814522, 641219071, 69135317, 458942027, 1030452320, 588315524, 799039781, 60023674, 553637527, 597413230, 105408060, 92294936, 181313116, 468588072, 465707751, 512791290, 816878033, 464280393, 684273729, 524770730, 375974707, 842740899, 49928896, 431871699, 152492854, 404606511, 998559022, 563223867, 457447294, 701623131, 1014591275, 11173289, 639040887, 682792950, 924698452, 624124851, 714539496, 58026675, 157659079, 717661947, 976423402, 842677166, 89726149, 939491362, 719795073, 884451616, 643536118, 964575871, 894278091, 736930831, 621556170, 163004760, 367245630, 988257127, 477790073, 852945496, 139468846, 746537216, 633928015, 1070419415, 902695896, 34228288, 511315339, 357911677, 959307658, 937433726, 186469480, 672532295, 865448270, 652509742, 434781249, 1009313863, 230886340, 47291117, 128924539, 528184667, 1018680975, 54294298, 413517353, 207069261, 369460251, 171728702, 377119007, 1050383214, 18250592, 519475267, 177739484, 16236548, 438634632, 958513549, 837547262, 218005221, 901324078, 333869668, 144749059, 885659502, 518897810, 453294456, 207696318, 494373347, 865173173, 68898146, 237009482, 136895003, 959747789, 130684052, 581078117, 331408796, 629604811, 968401565, 459436080, 8157487, 777165367, 654693933, 1025744443, 523668593, 50930359, 636613843, 1012380970, 21403907, 521774185, 184641204, 22909095, 525337833, 106481133, 772471715, 17047954, 315995169, 874382642, 685108764, 1053695112]]], [[511, [543710797, 1052269848, 855125705, 426501989, 1028888386, 232439723, 548552514, 122546623, 447505063, 37693568, 780095556, 1011662837, 902864793, 590484428, 1030694488, 830112457, 1039404640, 1028536500, 816332255, 606195336, 1041317156, 539830997, 381218044, 161910325, 737416170, 1884618, 990294396, 577560608, 471961110, 713160758, 18586880, 539946562, 343356604, 260011938, 900028143, 370989510, 174866030, 931152664, 561749619, 739678490, 829616589, 352921530, 97900262, 480696265, 940224694, 789303126, 194329780, 118744506, 535178192, 395341411, 464319612, 351520274, 1037846750, 308268696, 213449816, 253830329, 406028369, 74004538, 342790516, 188886079, 958919503, 450922183, 26273209, 854529772, 265195825, 285810976, 416690466, 24758555, 704951442, 646026668, 637038946, 783392093, 106771638, 1034247055, 492710524, 838108405, 182308444, 704641494, 969795428, 26495425, 237763740, 522142475, 765853237, 794932079, 287834459, 483876810, 201177843, 167758834, 287227338, 196575115, 294617644, 909551121, 782326714, 227911711, 724769585, 690091450, 63926041, 403550555, 540484624, 62945835, 983189693, 758273902, 459942535, 156667601, 279107799, 880732261, 644163254, 343539376, 615305811, 907310059, 193774491, 317720542, 901177689, 112178205, 34951072, 84838840, 363289395, 551646238, 773658078, 917329568, 949160619, 297851661, 904107746, 1031518881, 791182828, 930665678, 79326535, 685469599, 730507549, 213757924, 79538213, 1049105263, 1025738768, 281447938, 944246947, 140948586, 513348606, 811522557, 285969289, 260441956, 137168308, 233162971, 607857369, 98621324, 285470129, 93906951, 206503605, 669473414, 513067725, 183848540, 116736233, 719897797, 1012410497, 655654662, 36389458, 79496805, 556197288, 698719519, 478025407, 422974479, 680936889, 837552437, 1023312423, 95231967, 725575550, 279977970, 704593815, 807455585, 975261386, 662367638, 946079203, 147462126, 555601214, 975908502, 303755021, 517014402, 378588843, 768860197, 93407368, 304874433, 869782085, 566746722, 384606263, 496889290, 377368437, 413919251, 282447379, 227949046, 615009566, 496681861, 124277968, 472369274, 920174433, 878300434, 468898758, 681640605, 1065729859, 12708952, 420591283, 1018209272, 22586654, 253539556, 294149451, 993500351, 110360946, 334182268, 397701677, 378442574, 705956280, 775763403, 319177434, 23879415, 791182466, 469829232, 888419062, 249609166, 627607141, 478338297, 382963236, 332238482, 404408068, 310339180, 245486012, 485823756, 3673375, 379210598, 443887577, 687578028, 590035636, 103211862, 698372441, 792062599, 889600195, 807895711, 672366478, 250448966, 769851993, 884264489, 3326214, 85787219, 871163876, 508454683, 343986298, 100184485, 23966129, 772088545, 17817830, 283480224, 144131721, 233625609, 653657952, 11502017, 252443878, 923596442, 336239699, 378880938, 522530011, 827031267, 874999483, 478678188, 721089909, 451918359, 819521603, 81436373, 878728954, 194708886, 871859321, 226504970, 559075325, 336355687, 173263649, 784996928, 875558627, 761340124, 301426478, 59456135, 126830172, 808448778, 439732488, 643831427, 590725147, 242417896, 372412358, 31910719, 489369379, 963970627, 213376118, 599307608, 442252341, 67603011, 940458473, 252155487, 145142622, 990354115, 594118974, 1018151143, 581291190, 696603212, 999749417, 1018705619, 987561559, 144652961, 651244485, 308215202, 995647774, 494491222, 603509224, 522335413, 243668617, 942184614, 1020054776, 185482917, 369514595, 875326689, 364994249, 832743479, 356678447, 460898406, 237519396, 231054790, 156285271, 283974101, 337743871, 218133864, 377299641, 1048527790, 62301624, 959097099, 193486383, 882390690, 753310389, 674646179, 587600472, 854791408, 434834535, 122909883, 523893704, 1006566287, 480698708, 751645283, 375240092, 492663467, 901194027, 297634639, 190182365, 808182026, 278183167, 314676878, 306382638, 322830680, 395360658, 43259080, 165526033, 126600810, 193815549, 624048798, 546982204, 109264065, 558542640, 314705039, 236056112, 582697374, 965970999, 308601769, 571934415, 316411158, 543382818, 1053638019, 888789886, 530199682, 327130586, 103147125, 791723884, 443399218, 1055896200, 581586507, 282125138, 248230063, 74846301, 698888985, 321670912, 343459604, 62821524, 817769049, 965621722, 507705429, 69777501, 861152800, 830011931, 1058027999, 743196305, 882725216, 226578410, 195444202, 142300573, 497235456, 893452413, 564317143, 758832704, 819596263, 632343939, 69100126, 357750619, 230315155, 304803846, 1035660279, 726189374, 420940193, 308225967, 266119465, 783065047, 980207393, 337370033, 29062172, 659757805, 277372142, 322585171, 56205683, 402278775, 427907595, 23365601, 66440774, 772684601, 176272292, 1395491, 358725385, 896700111, 329609913, 613611360, 966475241, 81107161, 10233294, 592351485, 723768693, 358141098, 56446757, 813126168, 707745972, 245759808, 539885193, 839320198, 330046928, 685097821, 990366061, 364032505, 59494699, 539596975, 756759878, 638698731, 887013695, 883930257, 561717399, 297119760, 787532740, 477430321, 1040706326, 254864675, 987598594, 36378558, 744010434, 776706813, 296327902, 557389366, 265491337, 404294756, 924527449, 980138014, 316892215, 745269654, 651697395, 132372205, 1022110062, 320355576, 910592560, 102899605, 157817016, 681484770, 96591340, 799351677, 612594921, 431038277, 437503265, 325700740, 537875436, 207194695, 856950499, 97051036, 905283565, 87778879, 803683310, 651972259, 946542684, 680951058, 371937416, 930492302, 19212485, 642831655, 369677778, 854297830, 150775954, 899591576, 376102136, 945761015, 947231381, 346862469, 45590956, 755332358, 558611634, 44006648, 431358368, 625942964, 726675193]]], [[511, [539150668, 601602120, 834511258, 936322143, 346345557, 18237589, 786362115, 787320945, 392873410, 137732841, 1055772302, 531764703, 124442516, 896649985, 53908491, 671472506, 994154828, 480523657, 628914480, 238002160, 102735887, 144376307, 478216819, 23022582, 357006858, 1311401, 576965630, 517208969, 835808492, 800775583, 973965660, 559295222, 911160742, 547065768, 617605210, 1011077825, 820315236, 382203947, 358214560, 423868838, 68926088, 526585468, 726808103, 378923118, 83076765, 256988407, 123336403, 111045065, 833019305, 767781640, 314476538, 109205368, 813010752, 780030277, 827991088, 818108613, 764411762, 772052442, 851296182, 987701416, 481478214, 43326133, 616850387, 217799058, 597090000, 259737206, 713129584, 286907826, 522305360, 472449970, 923449572, 191468054, 339648027, 718691755, 299532216, 187762286, 149300380, 487555978, 360024979, 45218106, 315546235, 134876486, 18074598, 28153162, 107787126, 767710549, 97197305, 295828280, 580927901, 514212425, 1042260363, 1047113459, 305051184, 294469988, 898893942, 980589745, 999716603, 907437256, 603163331, 357233768, 755053970, 174327108, 80892543, 774045469, 701509643, 913109419, 68450940, 364220220, 353881500, 80270563, 703022663, 327503526, 301413449, 549960976, 904413451, 352472291, 627563271, 498912193, 294565837, 1027445961, 595696903, 226253267, 622251890, 217116558, 513863319, 1052106410, 185511840, 122551876, 177684248, 244541405, 675270971, 1039309290, 635695791, 646441085, 740015079, 844711193, 597104430, 365826258, 253481442, 391412040, 539913746, 715884108, 459797853, 409019427, 574419979, 96302971, 955641031, 765003804, 597967031, 862742255, 739808307, 138434734, 651707957, 26929741, 920597363, 689573584, 5235679, 12511254, 1033212787, 460885692, 728569203, 1059969546, 395077111, 466559970, 559819594, 490282668, 707650000, 669123569, 749875700, 342143061, 487895505, 195329779, 828461305, 208980459, 996079024, 1000926218, 730872543, 164397572, 327610408, 476421840, 271210639, 958327471, 301055089, 67388439, 411196718, 351337925, 571893354, 219927555, 22328303, 437248175, 40583053, 129548484, 1072297269, 281824260, 279696682, 407225014, 103256148, 489009505, 963275470, 614159103, 753106109, 932836471, 44994092, 479689704, 458171546, 310030875, 238462302, 584724264, 1047049879, 359022727, 377145880, 758992592, 954256007, 176284489, 917512859, 201783320, 559008914, 423715145, 434540276, 623658965, 619220065, 249488042, 322799736, 677502964, 1048110415, 1017594837, 802903120, 75517964, 290136662, 17804088, 669830639, 479844155, 898182203, 331127775, 182310820, 463069199, 530847694, 336857055, 35923765, 103730231, 580716611, 244713689, 886107921, 1005521700, 501632749, 792487817, 916556721, 263092233, 4579477, 156895871, 162377883, 899543211, 807854153, 627215856, 1026211222, 644071260, 836152618, 316480806, 632163110, 59436402, 771083126, 173862623, 634056460, 623761056, 717611096, 675261531, 55236148, 1031582610, 344293282, 397409179, 1010213035, 801766087, 334631903, 76289929, 666134776, 76470121, 944709888, 1014883621, 921247136, 388892479, 237436333, 187506368, 679614858, 184744626, 264236264, 820780410, 1043749936, 798104966, 809046482, 1064205276, 923140710, 91053806, 99235102, 561203318, 502240799, 696921042, 27575547, 893482446, 517489422, 348275859, 539448832, 606011940, 858686656, 300228018, 468896943, 242056956, 22032408, 112876787, 206136539, 637823909, 218057316, 662815273, 274437576, 987392764, 21055250, 125590596, 810962396, 916823199, 480596590, 292461266, 214603911, 541236351, 923846778, 952901034, 195817839, 1064010943, 817837233, 717399862, 186508854, 524028650, 687856635, 352347355, 394635622, 415978858, 397415364, 88288833, 1023576808, 793495456, 384334305, 168526714, 252968122, 84162088, 826264697, 319807938, 224346526, 258663174, 601557274, 42583153, 483255247, 478418566, 722077144, 611144692, 360387542, 686807878, 135441014, 906021056, 172810119, 779571971, 97960050, 326167754, 529832077, 978051339, 600170246, 506365719, 562883263, 931707969, 903961000, 322988341, 147041704, 996391125, 1012392301, 57162284, 1022981491, 120641385, 851165420, 500862478, 648785682, 598013188, 288538442, 277445296, 277403412, 208839925, 477285217, 787653926, 477305238, 468760100, 918974821, 216404539, 155623219, 211929375, 794359844, 221493692, 756667489, 960432121, 130808653, 803031393, 31333431, 67093947, 864693800, 34841614, 282542325, 49648254, 403578980, 539321062, 872035108, 547279453, 346640957, 587378334, 354199092, 188588061, 751398497, 769712314, 428707509, 834780543, 584274069, 281232654, 424444125, 1027790610, 579382886, 394912524, 1045711148, 56588862, 651118454, 682274618, 428613657, 1064016353, 41040996, 302052459, 667739329, 193950501, 195564229, 976323107, 275324376, 192368092, 968131622, 100834501, 261985583, 292986235, 360812381, 146806975, 95273529, 958855724, 259832700, 795674527, 627373450, 1001508373, 775033638, 5966207, 1029138280, 1009507645, 785328759, 397660316, 227073651, 325334533, 927434660, 202534141, 836143337, 9746356, 1064101650, 1022308901, 921985475, 680978516, 921572806, 671934589, 744073872, 262651638, 580430528, 723413425, 540369492, 913492572, 1010043291, 595209459, 429241570, 469315370, 432782547, 676159375, 987296998, 968172791, 300451452, 134910801, 586297552, 1045441568, 29662382, 335383832, 487920090, 453262672, 998793307, 401446620, 551682281, 425010949, 279842649, 130657252, 409967009, 744815956, 41449526, 169857331, 413554116, 431579950, 1058658050, 338084203, 114306987, 239651876, 783398254, 1007317276, 736493298, 752242577, 782809379, 888405698, 378669502, 13340652, 669338514, 198468921]]], [[511, [509847918, 305622963, 171211395, 619187957, 327214552, 996417590, 551668917, 352667404, 221741512, 838227925, 56596109, 323481371, 941225028, 265482193, 217367282, 576182481, 959421259, 405424784, 827978784, 163217173, 306691524, 839476938, 459077202, 546264908, 1067794828, 776866662, 310567784, 376617179, 214819377, 890569373, 898197076, 687856370, 461548149, 513256939, 386141671, 837640776, 449281677, 421178030, 412683495, 618473376, 273129823, 321769164, 975423122, 826419249, 1052638166, 77753872, 925720343, 611011084, 467249650, 1042053531, 741169430, 336147977, 881304285, 642959226, 243873903, 548172329, 303225584, 594184614, 679920354, 420601149, 546749079, 691355433, 337566623, 467593306, 704125741, 136304911, 936235508, 832059489, 648748591, 649661403, 814080966, 877581868, 27439331, 254670624, 976407660, 486528238, 101037774, 779860267, 921476924, 525197492, 604638109, 926407670, 675575891, 283872698, 174127574, 749164763, 190704438, 863598164, 223837182, 440004524, 738236676, 620834198, 950168782, 284783326, 789584969, 765673104, 941561780, 796835713, 653906966, 325528484, 34975553, 676135496, 899365861, 179882873, 908139565, 286728888, 946718912, 323424234, 280218600, 1038951072, 395531827, 739565486, 1020623783, 426749233, 205759270, 969805328, 876693110, 328019961, 259687066, 981056640, 240041150, 64095335, 113330799, 173778444, 963524813, 983530792, 585438183, 845303902, 840063053, 253192132, 782983737, 374352834, 768260410, 1013278995, 50502388, 762909388, 157119279, 33297142, 374880063, 296130418, 99630526, 780724401, 415554599, 771324308, 788030232, 101029784, 684742621, 390484708, 601951104, 6973250, 379442348, 626801253, 828020485, 322000502, 810521349, 128734603, 774362313, 254892517, 866022811, 564625382, 215909823, 255875332, 211103871, 514471534, 582999648, 458210853, 575511100, 1042019943, 72158989, 304404145, 51576570, 620037700, 1004263149, 517728000, 588465698, 11630285, 16695416, 114695033, 626199618, 345015473, 473170201, 752600778, 625557784, 965827160, 578188759, 311180199, 950590334, 751626021, 506658458, 974385875, 995951370, 615092717, 770723570, 575479850, 40240140, 726933702, 977032278, 490846287, 445054981, 128772465, 324492003, 7452914, 740661774, 177329014, 315806185, 536469706, 953480887, 183950572, 94761062, 992927293, 741949723, 169689758, 122756387, 193338200, 286225533, 649876913, 479651636, 844080216, 492646950, 254144337, 914672758, 469203116, 87936711, 417732201, 278615351, 634564037, 861951238, 909136045, 265004446, 1019052618, 860499106, 779130216, 391365486, 1033453427, 895003205, 78432814, 349939845, 635389384, 411047319, 855949062, 581557440, 691356820, 911934465, 205579418, 468922251, 817374261, 67816796, 428801646, 188688463, 455273532, 161765831, 746141474, 870457266, 302629531, 491790800, 917111751, 65432849, 446933225, 928576825, 789437034, 603911684, 228233353, 235905457, 766114103, 142095763, 380396431, 47538626, 717842863, 181516964, 536487533, 576887773, 1040440982, 582546866, 79414453, 39816346, 752631059, 303280110, 1060895315, 808295338, 3886622, 375051733, 185373198, 1050559031, 341875329, 981802189, 40327191, 82370841, 181478204, 521416523, 560922946, 628741652, 489078495, 408476964, 521836914, 318871469, 206305596, 845121781, 843510325, 238977270, 237619802, 505630101, 1017730021, 723604076, 1008711273, 698780801, 287457778, 439322970, 535003462, 363668975, 783089504, 407787708, 1009222847, 1052511970, 1027112364, 936301865, 205693622, 12225931, 254358287, 72263702, 847980045, 326078496, 767897568, 168597459, 604855825, 271590798, 741673707, 916790228, 901103979, 430156686, 74050076, 406880620, 311807844, 1040992945, 968290473, 777084211, 126337129, 439015003, 504384918, 1036375190, 674994399, 324368563, 620160520, 343809198, 52931799, 78488586, 928193715, 261580734, 49791920, 377139858, 410712835, 841506078, 109106338, 548570590, 164255728, 768081281, 39983885, 302150711, 480825082, 392693411, 249639580, 264601020, 630632227, 168244725, 197832097, 502919863, 199172641, 1046018793, 456339513, 203803641, 143485826, 846835963, 190519895, 756861417, 62162458, 116459219, 192624125, 268861747, 732147680, 656609536, 419191103, 318408287, 803852072, 367499538, 752759887, 662247982, 620211194, 773555866, 149189390, 731052688, 1052644610, 739157732, 251533872, 693676410, 1002385190, 178792891, 898885099, 428875223, 278467381, 404881478, 373581394, 297004920, 319593887, 943274563, 877115663, 818076140, 150327520, 638438168, 390446461, 513532231, 699368106, 1018175920, 645230556, 354132057, 176230356, 71246945, 420823729, 247558845, 481032203, 914972899, 1049060565, 205239586, 52952909, 408709960, 910392472, 51059564, 813071346, 83280511, 449211393, 754721027, 820620682, 652263411, 661979453, 649440140, 132639731, 450446432, 304256158, 878773059, 528431467, 484736602, 733240958, 522847984, 109211381, 315267785, 22753446, 993554312, 757866853, 835278228, 11316425, 173709408, 328974159, 397558084, 490822363, 689950485, 698256019, 206998372, 286630809, 108577525, 130118133, 503571056, 310314209, 292006353, 320254260, 53234065, 599751037, 723989003, 512409976, 588392138, 712789265, 436326986, 594793500, 775691374, 661687876, 467071269, 576452831, 363408662, 353474674, 329288902, 287237077, 65478017, 390139558, 518750631, 912687498, 48786565, 545827008, 37147769, 806568960, 717605160, 215870346, 38746597, 867798851, 607975192, 1057723516, 229130355, 640374689, 159727958, 322474660, 972857235, 776665170, 1002914827, 495702648, 746909963, 1055582940, 339845609, 622266076, 389542451, 241326179, 779266479, 98433262, 50819045, 438683682, 865676296, 417166172]]], [[511, [875429488, 551314340, 9360205, 682034507, 41026333, 297843709, 312807227, 287315005, 554675332, 305962695, 541922344, 467511192, 34839974, 537402310, 823275692, 676331102, 140388267, 923982525, 22918228, 209605207, 61335362, 385913222, 1048030762, 899879812, 946431035, 178439319, 780658666, 227650521, 124061790, 922348054, 125184475, 226907654, 312046845, 662269133, 23475365, 632899437, 697760176, 82790296, 71101764, 791898542, 598762822, 197834152, 895654857, 318416786, 755337698, 598214271, 92729544, 490714219, 491086119, 694648457, 231066890, 115590526, 975171905, 309442163, 616407061, 150769252, 162577365, 271283757, 585253756, 808377330, 550911492, 578404840, 611776361, 944747339, 493190132, 488936897, 1002937061, 1063519425, 63236078, 204267755, 424945651, 806024832, 920988460, 1048893428, 479578813, 746291069, 756567752, 749468447, 165126972, 650481384, 1024919682, 850877585, 941960103, 819490595, 35970049, 981854402, 750591637, 564776696, 725420111, 626264109, 9969030, 248178661, 825513170, 629747107, 359451533, 951472833, 3144692, 726702201, 169608957, 439171314, 213515076, 162021629, 187343097, 1021838393, 980587805, 976385773, 743917506, 624395835, 641689792, 618102681, 452776693, 228705396, 1009728394, 534289626, 709659865, 914746082, 493816475, 709767981, 248201220, 641556902, 621521485, 1009351435, 76543570, 537556253, 76267825, 992874979, 1049761960, 1066212338, 609517961, 760171865, 635835602, 56567515, 524236467, 685106574, 84757177, 649443702, 560493860, 168021317, 667215170, 491328535, 234517033, 473666636, 837930523, 174519468, 181449342, 884077912, 533340469, 860996280, 423798343, 180828869, 120796895, 422425286, 715946088, 184729351, 276280898, 490489606, 118744616, 286174555, 976000417, 415783793, 916077554, 742721670, 66606702, 496361881, 335334820, 757279916, 945441010, 787371591, 791600758, 574682579, 346714887, 322779494, 337593500, 402601469, 294182798, 359900531, 888863651, 956357148, 85375298, 672667108, 764981905, 344888067, 729276389, 229096963, 1038003351, 489155736, 353833097, 510060477, 66731551, 542691558, 846149749, 603670835, 609890866, 680191548, 564702699, 216586565, 932613854, 820570497, 101704174, 448206105, 445015672, 250469590, 885514901, 232712212, 14240155, 662287550, 352375881, 976332697, 539138893, 583236321, 503530513, 470383304, 1015387663, 479707965, 149961857, 129982624, 118167274, 731556401, 226516508, 515338428, 346813395, 796140274, 965608057, 158687186, 852790120, 644270888, 342064407, 612955936, 24270283, 867311668, 614167902, 775331325, 224276251, 797260502, 769980629, 895893155, 843431461, 28935361, 1067371782, 48381105, 823258362, 52387537, 731724082, 871743327, 61746695, 381092568, 805535249, 571651220, 870175810, 681758343, 910583371, 905803438, 866977042, 362313125, 20808461, 290618956, 539849597, 981136314, 35382099, 60641032, 435277036, 789950912, 49114870, 1021164307, 840904601, 884746991, 372867980, 543680107, 216578517, 837782262, 772716163, 329322014, 1062296489, 306859006, 997639629, 56073859, 420507407, 67666363, 266278392, 800876253, 337225812, 753754363, 843509104, 724200517, 525956752, 429272583, 148163712, 93865799, 755006903, 266396590, 840728453, 476188380, 475568841, 207318842, 651069374, 412476543, 1013599863, 389929433, 892531228, 259061657, 716332437, 965996110, 783287940, 78270185, 82740969, 1842207, 858440000, 237164698, 52178819, 280363057, 798839141, 1053068605, 738486698, 217340599, 722754404, 636569964, 247808789, 742753789, 655718973, 117409260, 599265987, 898944412, 573030642, 366038709, 617264046, 1021487114, 646634759, 613921558, 99205201, 830472211, 390532272, 173812810, 1044718134, 51098899, 481940725, 717718003, 991303408, 595810185, 766257376, 821322531, 901411400, 764375510, 324026603, 837514699, 172878500, 744620193, 612930607, 260240364, 110956109, 1027906915, 521585494, 806898369, 262803257, 979597075, 305214995, 354640165, 544857318, 365573370, 602277298, 952412467, 865185041, 458053929, 379538988, 505354873, 113097027, 337618277, 197504375, 958129817, 205934250, 403981464, 306444372, 719894548, 543390208, 437282251, 820184299, 82176381, 297796004, 362922348, 571527110, 752996771, 611618947, 58874105, 585173816, 966553956, 764408996, 550150011, 733957480, 494844963, 381553456, 516857927, 312756365, 306849920, 866713544, 81298854, 168018797, 300563669, 998073317, 483731065, 327723208, 1035863390, 511494753, 1037892358, 619846201, 126183013, 650282138, 145472326, 594583700, 642622743, 274095815, 1060887963, 937689574, 855485481, 249732062, 28621593, 73340682, 705322135, 418975018, 1054369946, 179400180, 5369340, 589987253, 427327155, 577184485, 243972222, 1057701744, 354984423, 78918931, 1061009337, 170349106, 330764375, 380421118, 405324497, 777657820, 342761619, 685271749, 482815450, 1010572527, 869305973, 838878926, 84992659, 160908326, 515044777, 801975693, 912982393, 871715175, 943790984, 567553834, 745079211, 312148077, 807675156, 573284069, 115242172, 608891114, 299150941, 957598109, 1043569839, 222039123, 528677478, 551571662, 87001681, 797653834, 69618201, 635202491, 24740519, 1019530996, 336658811, 210254743, 803531109, 277769101, 928070006, 141564989, 175528593, 985345232, 479595540, 1045074018, 603794, 1046813438, 208656767, 2695413, 451400493, 876875890, 937439155, 811179083, 731333374, 139896979, 360119476, 991704521, 493112547, 336157665, 674867065, 826652086, 906362773, 387943046, 1016047658, 856171051, 242186159, 960586490, 616039532, 164351602, 550790245, 470464498, 131877754, 924975002, 264182296, 694923686, 307692290, 749731251, 48378975, 212204586, 976484028, 1677178, 5721747]]], [[511, [205283110, 398266379, 667165839, 1023404018, 200412667, 385676737, 300392964, 616891834, 805220812, 223836916, 620607679, 702932217, 463935266, 815304705, 296998979, 627997889, 259429349, 995642603, 390718365, 1024139865, 448770410, 326411912, 1057228871, 634344677, 1067091918, 568570072, 839461138, 996454588, 296597843, 372222069, 392838228, 725891465, 358382245, 646731296, 336791310, 772415831, 220366514, 196186001, 521142892, 364706925, 1028535629, 517265516, 136423352, 502387051, 226552837, 997081850, 304299333, 339893481, 891849538, 789356228, 867766819, 328606658, 857253592, 321824834, 128220337, 360749906, 942801424, 1063653989, 840411276, 1058246433, 296782737, 1046964064, 675663279, 786701494, 304718686, 958409252, 64164347, 216000525, 35966345, 848727310, 274318755, 323240333, 547841504, 417521604, 118154338, 231393693, 285793291, 134941286, 246163468, 912337210, 815727103, 247137205, 722035168, 349035370, 86737644, 457726582, 813433350, 600995341, 203271139, 972137076, 588980944, 117555263, 738577056, 572864998, 49415550, 178556784, 804107327, 930424019, 186089016, 527442180, 675632133, 485541906, 140872679, 679563516, 1001335014, 766092595, 263988193, 1037593514, 710401001, 763024601, 815303823, 499084088, 982608590, 579326323, 253827823, 162197071, 17396868, 897398216, 614280118, 203056199, 1048466478, 341580109, 55839299, 318118040, 666043244, 68717911, 431790819, 220462192, 862888139, 753915627, 506281783, 1066390936, 743922298, 757629466, 357507165, 44316977, 973414888, 287764578, 687859681, 757170329, 308434210, 770995823, 1065088908, 969047718, 601064719, 263321143, 411622790, 672754488, 600377242, 774863432, 929225726, 849769747, 1025177571, 111411364, 675138453, 67445726, 672292037, 379659427, 504628608, 969672044, 296641671, 889934217, 352201958, 269597143, 143555883, 874188170, 39010579, 4056320, 481363738, 1069632565, 373424596, 765958545, 497659426, 368460908, 432763906, 613254150, 971215063, 953302111, 138336791, 133176328, 489699943, 656920271, 198093342, 605899687, 670793243, 72420573, 908437961, 197838166, 99100490, 385373432, 128728186, 1040662209, 190784405, 558373870, 509110422, 651694061, 1020439846, 128793572, 1056006936, 919479098, 738658354, 695430482, 49423515, 896900655, 497690733, 460384048, 39075376, 138950941, 966744733, 464255488, 55691847, 816286723, 111888940, 746673678, 1068501762, 127439195, 406131836, 623673811, 107090661, 657499629, 620827991, 617787827, 138217783, 1045342723, 445463479, 472249171, 287700765, 468150897, 698536626, 823080, 452374907, 298136215, 13149893, 590907019, 905441909, 304205362, 819562126, 119975359, 69446362, 274519266, 85577714, 753489035, 774100659, 692454324, 251082383, 86488245, 682134662, 1005583993, 1044430831, 485706369, 394317385, 343923327, 916835593, 455642545, 372584889, 764849263, 396946029, 781355076, 4673538, 471361887, 730455242, 967389793, 1054047189, 176174223, 1038777297, 400874872, 453207839, 690018389, 209406219, 768726958, 752059477, 430613771, 158616158, 319802171, 61543031, 171212600, 690194098, 853747078, 358257708, 1069420145, 103772505, 35967115, 219778987, 775286013, 160730626, 828594227, 1039257932, 354642118, 1011493524, 499632448, 966376261, 711323081, 520601241, 169106405, 957844712, 456880037, 493908615, 626905667, 171983947, 439431666, 438234072, 60851586, 389872581, 277977368, 713913643, 669665258, 948579531, 540551681, 1041437215, 985431013, 946289609, 401126852, 18637214, 304813175, 644779867, 670183710, 532098152, 807105502, 836638779, 752016302, 721005760, 63578814, 5399356, 763002241, 408546631, 51120765, 664616816, 625177110, 809096715, 800951025, 853377222, 677984376, 687336259, 862718868, 208426186, 232985357, 94684689, 172036771, 293185699, 714725126, 385997796, 722156153, 915879090, 313677584, 572178325, 433136769, 604693121, 689115495, 343158643, 743409792, 662793863, 264937216, 730736636, 1069917997, 63453042, 1047618243, 359600439, 5297708, 88229456, 918084301, 986502166, 174343763, 587168530, 475265086, 388024622, 833228109, 602502026, 950511526, 743782601, 58103980, 919851916, 619744832, 373501372, 872116741, 528487161, 1050932900, 184336104, 685950390, 792381445, 22472313, 833813634, 546373497, 914250805, 241740421, 79792440, 20884901, 348454670, 336629330, 879822479, 451205571, 590705048, 128460682, 614094421, 480165343, 524802791, 1033199128, 434863188, 133274700, 235417332, 687858971, 336747872, 326395679, 445678326, 466081910, 410777254, 459200152, 492453470, 217416116, 1046049971, 875572054, 606812432, 510759285, 493870635, 420439717, 1015982105, 117217168, 826625847, 483049467, 525250338, 467287667, 40902367, 45022330, 646416061, 766507604, 997774509, 875350624, 312803667, 195668703, 420326868, 460596658, 682871969, 251456967, 752897451, 1065650294, 377356023, 542909782, 654622183, 966979915, 771439023, 404721829, 568364319, 370599635, 595926092, 545995846, 865083103, 180765523, 623122227, 913337258, 33340614, 139562079, 309070031, 248245065, 390341604, 690838308, 754461908, 788490291, 99449936, 989754928, 238975720, 106727709, 1036504782, 846331492, 338962055, 1032163542, 564220744, 583514405, 94233301, 354520917, 768328197, 33927806, 761678135, 453568047, 138986870, 544589353, 401776221, 862195542, 914935969, 273338759, 157421464, 817139006, 246656915, 523925460, 919044820, 521691876, 317708553, 988892852, 401408090, 341567590, 492246128, 1065026287, 598410771, 1027476703, 767283705, 199168310, 186381658, 1024798419, 215286576, 569065855, 748088766, 293490541, 484943007, 846419404, 631703914, 5492375, 414287489, 511205858, 1018747500, 1072929342, 408847539, 769910898, 804584950, 499817896]]], [[511, [976032580, 484658913, 562027175, 10614388, 119355337, 502193774, 1042131860, 156225339, 914860051, 627298998, 1066476693, 695911894, 318685719, 567882012, 25082318, 910909014, 475698614, 586304999, 675033641, 84709471, 772848234, 569395086, 714414399, 826513728, 622958226, 146108915, 381796924, 916429186, 278820285, 528001649, 99698679, 77582241, 981427100, 928173978, 131852068, 651480944, 876857469, 50753964, 252427746, 483116529, 303720452, 722404215, 28378980, 914843383, 110969718, 235869145, 194381191, 1010370341, 541795027, 993758468, 729208620, 690190666, 494397882, 184659757, 91685513, 238999184, 978313741, 1055994809, 912579944, 1017963073, 1048740313, 141205803, 834326581, 320471990, 460315424, 356198473, 498037840, 140298562, 529059485, 724752382, 305901657, 197768355, 693705005, 233593579, 562941575, 956139614, 1056151267, 574025251, 394195445, 448314529, 986985135, 738311205, 864513524, 952526526, 535862013, 980592822, 1071934017, 773405331, 226149823, 210318465, 96292947, 189329658, 647620087, 463416101, 909819443, 921079443, 330405510, 59918161, 666469185, 145497504, 646801363, 885963792, 84787557, 201171774, 802035609, 241977045, 797781309, 485022828, 419385232, 240573780, 809511492, 132429528, 973628122, 338109759, 645318084, 812721982, 127579032, 417001380, 12063747, 539628602, 676439417, 226631001, 934071720, 294980020, 183435568, 719750436, 1001413818, 295114450, 143972215, 1023955443, 416255598, 648424312, 152341622, 410116634, 534091826, 239986659, 673086420, 756787188, 987685673, 576712325, 1065564839, 524981369, 567458907, 847063208, 545078617, 207705935, 132795624, 664964802, 663025952, 719858220, 40890160, 598158355, 609061587, 1067844272, 76328759, 1031064670, 477750773, 129677772, 31988382, 1068943941, 531462870, 756187550, 569618743, 416718211, 1018848103, 1031266904, 156522856, 603602625, 501582684, 705113848, 768458156, 723504682, 936409649, 615200302, 683994190, 137114281, 126165751, 172374681, 352987062, 308950578, 671543960, 339437828, 275739149, 60107816, 715397596, 629566768, 522080481, 203866433, 1000170238, 88361184, 410642021, 829757798, 873432812, 187753327, 110508330, 970861143, 778902720, 716090458, 359859433, 289442285, 131172574, 12537141, 1054865614, 464916582, 467347170, 654264159, 852537729, 98994941, 771675932, 165187597, 187542882, 268274488, 484524235, 1064372502, 494297354, 579315972, 155327294, 95951987, 154678601, 757065600, 942233995, 496778699, 87166708, 24204608, 682356495, 925379870, 241595761, 937906614, 609958722, 1023372500, 462970827, 484090665, 968647339, 618251947, 661638124, 148063332, 292962408, 766744079, 832635071, 534999534, 1071961667, 889536013, 392996145, 429878477, 464275686, 641324200, 966947615, 527333691, 563712069, 68979157, 334579545, 748927676, 224494634, 578111440, 401184595, 55332335, 210911539, 424835730, 716803169, 894790279, 766160801, 64754122, 131270908, 468945915, 457245547, 286191869, 1059935454, 427803369, 1068581047, 310384548, 574275756, 678375948, 954917115, 555852983, 1007742983, 783860457, 295540534, 859639455, 502797879, 859526770, 820838099, 335170449, 432272348, 78540452, 921600579, 876183023, 754384470, 344410132, 684406837, 844837783, 380851459, 734859485, 66826467, 965372889, 39848840, 566873885, 420429977, 246497398, 1028699831, 940552246, 18602470, 901918512, 1062379918, 919485028, 451081609, 561718208, 165398966, 49149912, 913000008, 582183221, 649512380, 708223699, 411538777, 140687281, 494269275, 676532858, 999657919, 471583744, 629747856, 884564884, 577743896, 702976056, 518240330, 503753865, 90786961, 328193802, 887689440, 466944628, 663162393, 1039190765, 708138630, 373559444, 397151160, 600218902, 210103548, 70537671, 509745565, 67036631, 900683273, 270016996, 725883049, 62316764, 380093727, 208692330, 614607007, 586557528, 247720102, 596151084, 994944782, 146942364, 446522791, 162225170, 649859959, 998864431, 131753427, 207478394, 304953684, 648472323, 1059428967, 404407738, 894997015, 714244298, 716969939, 345106353, 488736025, 786513579, 605950025, 166480221, 947477392, 814694445, 311449148, 738028465, 1040395257, 255391366, 657340285, 618499259, 625723492, 897247624, 288303587, 164934803, 1000433624, 206553618, 265838173, 733753753, 916242973, 370498860, 953166523, 923955581, 1068232957, 339342597, 624445759, 193596067, 157945512, 244098839, 713855746, 153028677, 115097711, 1033133891, 856128859, 885088153, 1035736757, 152847358, 360008789, 412433486, 366260720, 84130580, 433539903, 693424647, 340946871, 414828478, 909392519, 516681586, 486033742, 202235647, 1036543746, 1026652728, 904140449, 691692994, 595640763, 1053670168, 969352092, 585839750, 770246233, 101888311, 711619028, 155471307, 897701704, 564286660, 962875387, 518807237, 324018604, 349945468, 968663824, 519628413, 993651586, 712237203, 691321168, 611937557, 798322191, 82594348, 125419137, 593494767, 296244508, 905247216, 679463643, 765903809, 556786116, 421933987, 987531018, 892115876, 220275708, 36160265, 75272030, 294672845, 650877949, 927158683, 952040941, 216475991, 946322288, 638463684, 252464909, 1025775872, 302874832, 878149783, 907287371, 703662472, 302008227, 116230216, 289686933, 642310185, 404561417, 681799070, 216426397, 773293052, 912996445, 527350592, 839192365, 898726203, 531075914, 476568478, 124218008, 657325665, 537463041, 822471141, 356348804, 737349973, 534749999, 21770017, 160839988, 77769440, 1005338810, 381991247, 832914799, 586647862, 698162420, 908554356, 280760801, 370987072, 522137381, 358435256, 46807551, 982359651, 459254009, 568307673, 849397602, 870628079, 554831839, 731000042, 618126442, 1012437445, 610039908, 903599377]]], [[511, [568445555, 1001018132, 210129534, 201461486, 575555254, 599355249, 705969158, 587237152, 70219897, 437841346, 620048092, 950900710, 635612054, 107672937, 64442529, 474234033, 319902511, 790764551, 696690392, 625349788, 216167049, 647934407, 601829234, 316713124, 959468073, 890390290, 550213064, 848765517, 1031957093, 35924606, 450355559, 56784769, 723318890, 137839557, 618868025, 1013621296, 401380749, 499595681, 117001336, 576392423, 255902269, 1042287485, 809044006, 319827704, 1047993650, 531146247, 588161162, 950603669, 372614956, 584057738, 980421508, 16412489, 318304485, 25743002, 514829532, 519919653, 866474780, 586650688, 627148358, 867440321, 1020056726, 227970104, 785620281, 540960061, 11188902, 164481251, 1056878430, 423910038, 331993153, 140326267, 204749594, 122347053, 781836028, 343632211, 72299856, 1005385579, 342538900, 369792203, 75334872, 798760794, 1019038899, 967649994, 183311206, 894680559, 296812657, 409392262, 186936732, 700785184, 974062704, 578142925, 354295350, 13710407, 284489904, 180302808, 642300744, 287568893, 123290333, 303961121, 912218261, 868163562, 460453045, 856425613, 130547691, 828948785, 722312019, 487340339, 78413657, 823953556, 994611875, 129005286, 660208235, 452338672, 1056978236, 1000748275, 932871633, 1031185115, 111875335, 989211361, 611299588, 179075204, 557092494, 883557632, 57963631, 716847038, 564504734, 940079003, 9262629, 447162836, 742954502, 857499395, 1067036278, 606183035, 958273967, 197038409, 75740630, 315144423, 942045931, 1563200, 615953847, 487085156, 369664634, 448203438, 490010249, 117410692, 32516802, 913213116, 33040316, 216316066, 224258015, 145815334, 270550176, 688649646, 198813395, 729979992, 43980389, 575622721, 775658400, 774748436, 878359227, 710108420, 800077224, 1024721633, 712291478, 336938327, 483559572, 793449289, 492410147, 823954766, 458876942, 582509814, 496130006, 91444795, 658527903, 581233498, 120907542, 37957020, 884067785, 714346510, 639458320, 651221303, 905724240, 4421526, 761310950, 917499208, 784913371, 712392812, 1030185773, 178374723, 1023526041, 246654123, 240640004, 356128144, 314146779, 386991547, 1031286673, 585808761, 424281984, 783593177, 413098569, 695256834, 821860336, 18250385, 873018483, 881216361, 672176622, 832162248, 370518255, 663434585, 840823837, 24047331, 369850939, 532854954, 1028156271, 312186809, 371925402, 367546597, 31905660, 473768801, 1012719881, 93636033, 493084183, 1053834960, 468313919, 568093815, 602847580, 1017577667, 207998378, 1003675515, 496314798, 151066300, 978125333, 126584240, 339259874, 997826639, 563273660, 68157680, 62574253, 296616205, 827793390, 175667996, 339664411, 500765263, 988756765, 583580283, 656386256, 263531485, 704047753, 714555384, 1053680415, 150465210, 262295141, 679495827, 988623915, 436202004, 27172738, 880613704, 161180770, 669806614, 788392107, 611314597, 820517289, 92172266, 924943323, 120045421, 444828770, 390485729, 443348872, 774889069, 638498083, 1004294698, 804170021, 772224901, 220505418, 404629282, 666486837, 1031025712, 1020583972, 734589098, 688464466, 1073244225, 665809222, 615672998, 515319907, 798334329, 7103917, 492871898, 525628108, 878088539, 964868135, 954377814, 1017762948, 790070967, 544521511, 380321957, 787033804, 145614540, 613502718, 411075003, 783103409, 912089932, 667446541, 323231129, 869220944, 336142034, 744884336, 441233124, 256191725, 927971528, 644924736, 14768062, 250321328, 202214259, 625900286, 987064067, 210430091, 779234148, 381446024, 140622598, 540696863, 894724487, 993553508, 99974801, 332379685, 789154030, 674353762, 629836752, 22616503, 739345030, 397162975, 704561489, 68536534, 398334507, 467724773, 681511247, 234293976, 971750012, 748093987, 945108717, 418291998, 1073167346, 533850676, 397432460, 351015994, 54365500, 835967526, 844890029, 206655180, 878674062, 361779590, 163487795, 889987202, 101048768, 626670108, 594881073, 188486077, 863254164, 229081441, 856715490, 66700614, 1066751992, 50985020, 12509507, 277537230, 956073964, 723466773, 530576959, 506545720, 605131774, 331089012, 521105360, 81261431, 80287394, 898309076, 1036719398, 532109289, 694774114, 458362865, 812787414, 977004107, 600570357, 333028485, 203882780, 933389781, 507492921, 309104256, 630696217, 737075367, 348882319, 678357226, 853414354, 366028354, 559414216, 576567031, 553469845, 814195840, 733581528, 812721323, 254672462, 865589055, 675471625, 1008896332, 950606308, 647043741, 204903336, 839496574, 602363656, 709737253, 867733699, 768092113, 228970698, 299366351, 155631743, 577248555, 214123413, 549564456, 1054983902, 231046444, 779712667, 614737638, 735658482, 157629454, 835180431, 328417268, 891164584, 443491477, 67963094, 7108659, 1007437658, 1062681260, 166900476, 474298406, 285848239, 837589202, 440647834, 498023745, 366353056, 725560499, 199234507, 560342289, 766223259, 625247210, 240048631, 1050027741, 185749956, 854037373, 1007572447, 79444709, 939657214, 895521425, 863512265, 663157060, 903675441, 224547005, 1031683334, 825918184, 1026564060, 1062392043, 678112380, 798678432, 482053615, 580050680, 284201697, 501511568, 242107183, 900522885, 435737111, 714811971, 616356519, 207699097, 610780966, 1072851765, 203305722, 720174464, 322399756, 869554615, 26826991, 551931337, 158130625, 58538082, 441418853, 926360467, 286465146, 20878790, 279040395, 155181873, 374882869, 711403964, 113064239, 518803494, 293097562, 1064866251, 425144302, 1060743544, 855321894, 187749583, 556297098, 882561418, 283439019, 783756808, 847655177, 329648839, 397047440, 4793089, 9967982, 64418406, 763126451, 149600194, 924499722, 47879079, 1059627514, 301308542, 744016]]], [[511, [925012200, 1042990416, 871370074, 1072279036, 1055725627, 26311728, 198110949, 809291564, 905367623, 462068810, 1046253306, 2999526, 60787555, 278113086, 731377728, 50155284, 34610056, 976784230, 818170674, 681113422, 592462695, 702700332, 187237179, 724183578, 363476256, 640323064, 143906043, 417565359, 44713596, 996677069, 320220491, 831851945, 1072233461, 542961764, 967784529, 832887823, 753872333, 718165429, 261317607, 89959081, 554766788, 745788239, 744840326, 74722696, 399304905, 848897115, 799421649, 446680656, 363215826, 175837328, 8876285, 650057261, 392575109, 276846177, 546981613, 620273316, 968297852, 648701511, 561940253, 25801538, 558324900, 800001838, 617998894, 208162552, 843989564, 376898706, 568783488, 940659774, 758390846, 239162165, 759108936, 477421921, 527384673, 546696525, 81398462, 896949736, 702074832, 473320458, 1647353, 1007534593, 426108617, 285965908, 407428226, 278725052, 349975386, 908769715, 331465350, 249045239, 703204771, 270746854, 791672190, 811953711, 759079225, 790959690, 627093517, 627907765, 634221171, 448392242, 893524279, 1019534506, 965825955, 243787423, 301384512, 703593221, 865801547, 574401712, 4545219, 408960584, 615793516, 730038674, 668705097, 278836053, 334917112, 502315502, 200555087, 190870051, 1046353999, 243935205, 1021334910, 98277758, 732685047, 393623520, 19960332, 310604038, 634159576, 155605698, 762501846, 651026121, 152768511, 371830668, 578051390, 991217626, 299893410, 306781398, 204865390, 480489310, 396615682, 668178729, 895447856, 734387294, 1057613305, 585855599, 682770645, 536917215, 1033341267, 1020253680, 727400040, 784097345, 355177113, 896555667, 309862640, 85084792, 102847855, 928011555, 252988708, 351685367, 493780732, 676105837, 416666472, 563033651, 163152877, 797756108, 792689831, 643309015, 261338295, 784603608, 216825815, 622304546, 134976541, 647409186, 241688858, 142143645, 268234615, 538410695, 559684977, 902604412, 913245760, 938948959, 52884516, 581653420, 107279442, 988687104, 871036432, 654473332, 641421069, 696854818, 982298178, 929308643, 371519981, 135294313, 1014808093, 973699345, 126973378, 212010395, 625971773, 707193702, 801691687, 60831513, 728279790, 822320123, 247230388, 1058261354, 1064161777, 617640036, 654287689, 450303960, 833378511, 1024689000, 190421526, 930693481, 1045261089, 787958919, 106097944, 231010235, 103370448, 394028432, 301364181, 327258252, 1052178199, 143592629, 104730262, 192913579, 278978005, 302610934, 767598667, 476309785, 920523182, 802884909, 1041894614, 72650498, 1062558130, 191722890, 695552800, 929009272, 423777747, 894358014, 430613702, 730236931, 796168175, 724261711, 741849429, 948782919, 989805576, 296572332, 1029203806, 238715261, 855478265, 1022251489, 688663648, 677169026, 1072800076, 521984653, 60279798, 618666421, 56891769, 177726590, 53928714, 613655221, 38558375, 249035957, 903711661, 373294386, 492153147, 880294378, 899578204, 1045607864, 634571760, 764926758, 841725867, 496728431, 641404635, 812854515, 452148051, 298279038, 573731215, 473906068, 45368698, 594160979, 895291183, 213984805, 235390488, 683401762, 471666786, 683781050, 737118843, 944524004, 479464670, 313907465, 456934321, 705777667, 168343746, 469502781, 325807482, 721722047, 611901818, 507250080, 763469414, 886522840, 633864422, 437571838, 489227156, 598454324, 669865835, 1052541850, 955473347, 682917110, 145723748, 39007559, 821014758, 614110791, 768164498, 452873040, 951429111, 785188102, 315132429, 1073388089, 708613167, 824162507, 540220179, 511192718, 765189447, 425350238, 694390678, 998882067, 25023393, 552844524, 462107422, 545834973, 517530136, 496390488, 318864309, 638363609, 358031659, 100549165, 157248533, 152331663, 724075007, 204745394, 542730554, 353014042, 467209381, 758258348, 7843448, 386039296, 603785863, 537739309, 86424438, 183136609, 216645219, 147280517, 748269154, 246366631, 800439682, 946603670, 380996877, 1065356049, 435330573, 867231264, 822335947, 17202894, 637867342, 178874279, 765051241, 639540428, 624308642, 78105631, 26545159, 596186297, 313100448, 1015569452, 515049584, 308668593, 385833767, 205154403, 483635068, 776089822, 780728827, 736833976, 539651443, 997417112, 1019344348, 914291995, 373052680, 89574524, 728040280, 205018042, 30736894, 490197543, 688465897, 419589908, 176980382, 884885175, 539521786, 528319109, 698573377, 69961924, 455654551, 131556205, 881783261, 344344646, 241887469, 586867574, 49194025, 939941923, 214431127, 611187919, 375707829, 543632244, 331061001, 190728430, 538450331, 755928397, 415040956, 362404397, 263167181, 266748461, 153415273, 59800466, 13103370, 29777805, 997819519, 505559078, 450191334, 317863225, 813005769, 574576071, 761724260, 927774450, 953424163, 347793994, 299895553, 148043993, 576969272, 745076388, 33076314, 236040661, 131488910, 375519473, 322521640, 445091147, 386900012, 865759928, 988213526, 493653018, 62308359, 1023140910, 138036486, 138017924, 665358594, 742543248, 193193442, 441919418, 710258952, 318193866, 275146515, 829324683, 393673347, 157822069, 808169625, 489269313, 820741490, 428060481, 333600226, 891960388, 652561844, 659571782, 471264589, 858163182, 43323194, 413342338, 784852016, 195244478, 573918721, 889793062, 826718279, 750850957, 552482878, 499433094, 184540660, 813790432, 46348521, 18471923, 897485863, 329114365, 650578804, 159258485, 1043105427, 504182203, 115656793, 335004745, 566804506, 809255354, 610282215, 525212855, 163854287, 845156597, 420136540, 753074558, 929085586, 600100856, 486074979, 635778835, 964033718, 545737222, 1056695022, 916667904, 622264773, 2363420, 644821514, 807628646, 885332749, 315044010]]], [[511, [910738567, 949959484, 34730735, 520153784, 821364767, 413604559, 634448038, 180587016, 22101068, 591432165, 1048971906, 718092229, 486584706, 206344266, 712464766, 793378893, 663017356, 610583401, 500080675, 843288886, 622194585, 956025594, 48713639, 222727694, 762347648, 889320799, 718807638, 838369726, 963834341, 805851743, 118044473, 736387407, 859603507, 904058959, 709740067, 221400686, 362653407, 214741914, 370171109, 278669539, 717566927, 726023352, 564118444, 183172119, 1593988, 678334953, 1041836590, 928238868, 632485913, 146935232, 689615265, 622801523, 544869222, 81356331, 77382337, 443693663, 133141193, 821330205, 250113555, 693269635, 1056673959, 217753537, 563839432, 78162007, 7588871, 278532498, 174148558, 964184842, 562766109, 57608405, 335361990, 502676945, 1015073362, 784005805, 949664688, 966017295, 132730349, 474376351, 222140176, 253784914, 556736845, 804616941, 71417615, 564363180, 878985699, 855944409, 486620259, 356897299, 370781863, 160935230, 146988272, 965146380, 746123153, 193279128, 560967106, 1056270361, 454755152, 1028030342, 598217441, 498322415, 787174285, 962413862, 632840318, 143840670, 250756920, 761645943, 447935918, 920387401, 62832669, 122276311, 453164326, 158726135, 265681029, 809056603, 389279389, 126222734, 348003331, 33433710, 49468519, 453384501, 441096824, 254324228, 927697919, 261008612, 696314140, 160797217, 764714622, 374940319, 534576756, 978307757, 1020419921, 429721862, 937185694, 479178705, 260071847, 414241967, 294152155, 1038509639, 1020037280, 46855737, 999931026, 939433422, 990162011, 335110810, 306928025, 792714169, 237226253, 518654602, 458812445, 547600623, 143249901, 142506525, 44860309, 295947677, 613369900, 320035542, 944697372, 753444372, 554104169, 302399424, 982634279, 163670747, 285841064, 110887820, 256863354, 186671231, 1031582917, 49876494, 481351642, 102275049, 680293400, 333649748, 164014156, 44491094, 345296924, 299526080, 984456825, 97739592, 636581845, 135867789, 392589989, 145879072, 664282291, 773339214, 924460576, 402785041, 541479173, 25190295, 137093558, 423447653, 123880273, 925000265, 1023306448, 225434981, 182554065, 594019476, 758913510, 213339589, 730650464, 751337860, 289123349, 1002893390, 1049092188, 623047445, 625835631, 605219369, 22185896, 895473776, 11341267, 602535713, 797954103, 890467634, 600863511, 454421920, 1061095697, 716051397, 1017629729, 457936120, 747891982, 107099498, 598273036, 298704001, 669689186, 632090492, 704234322, 600601188, 682085149, 538249081, 332391238, 987377273, 102876486, 115202480, 1066190734, 276810621, 209139456, 317746730, 310986050, 794759145, 464481561, 599318662, 1065315376, 316861540, 564059508, 63000293, 497391067, 613627740, 578199753, 595086966, 1018963585, 991342763, 159901670, 744280081, 760834096, 801807243, 106651321, 876657882, 1072766287, 84329919, 774273262, 921538014, 247026146, 222040497, 669461658, 224032065, 27353407, 775606892, 1023517242, 184335510, 630549032, 605152108, 335279570, 873810745, 1070391953, 418660003, 769416724, 14214830, 122889280, 960448469, 380445455, 543621351, 290052544, 85665707, 997845912, 1036215809, 1046581680, 580088746, 986925047, 859030899, 301813812, 309681397, 943737630, 655305007, 779773833, 635441963, 821482001, 147714588, 369306041, 728771529, 1002007880, 661682801, 948764784, 121815041, 642693577, 89799889, 1014385612, 513837267, 425066398, 566954960, 294666904, 154532075, 974039564, 813766265, 673962527, 425863031, 481285747, 793181360, 653466402, 532227158, 976124006, 155211915, 129214876, 510791909, 122137276, 437174522, 850189927, 345139456, 28058997, 981091988, 855558469, 770262396, 1037329684, 883863845, 710628660, 623771315, 775490083, 488104614, 24085144, 537821420, 445286604, 135087802, 894304723, 345572713, 492075267, 218452654, 926261412, 341919280, 597052056, 495939201, 984767456, 949959072, 470435716, 993823764, 491796368, 276950192, 178210615, 748358853, 921918467, 630098705, 96156262, 771481549, 808409806, 144430849, 230644643, 423607765, 1011489865, 416229264, 734626116, 292956337, 170729699, 107016503, 254355823, 765575832, 755908202, 223832148, 492860107, 558747241, 873522416, 409555264, 345582446, 102716055, 726126579, 1003726964, 923726517, 198007534, 584616455, 110815518, 428623644, 1056294369, 558629045, 447785426, 277803553, 447590378, 857716462, 95830980, 654793492, 1038601940, 568379735, 964724978, 281375242, 697354212, 119971218, 241209345, 768289949, 782293678, 555930457, 607443423, 659668073, 479753081, 564437448, 943313344, 750274971, 474571862, 358639393, 373150318, 675242293, 381205479, 798466644, 353085266, 736168134, 311753632, 630029636, 548775986, 549248640, 515127757, 244790062, 943663043, 483481140, 190921648, 879912732, 326749973, 329912776, 1062149365, 879509158, 960117960, 254386282, 778409757, 794428371, 700224152, 556987604, 1011348715, 978469682, 753785195, 561322238, 941935582, 640408003, 777603866, 24606703, 228625182, 909495999, 801553358, 678385990, 1059498269, 545413976, 75825833, 971317264, 1057625552, 935788334, 321168478, 21648756, 45305952, 70290239, 930019761, 995059663, 679077301, 417687558, 218357046, 1001078421, 381545136, 1038585965, 192865970, 223948331, 298381751, 914721876, 1022127197, 823262638, 103467855, 816503336, 722713617, 67516161, 605811954, 114211124, 418046058, 252652862, 985245420, 439557529, 195158056, 602276495, 767326499, 340332226, 173047577, 954641744, 791837949, 550582525, 393383920, 609491641, 324181609, 624888872, 73987113, 259563870, 549598284, 401287627, 276940459, 60122096, 610954617, 974374721, 717302601, 838760137, 375560666, 917646481, 517100824, 784300409, 838763511]]] ]]]]]: msolve-0.6.5/output_files/elim-31.e2.res000066400000000000000000000005711456710632100177500ustar00rootroot00000000000000#Reduced Groebner basis data #--- #field characteristic: 1073741827 #variable order: t, w, x, y, z #monomial order: eliminating first 2 variables, blocks: graded reverse lexicographical #length of basis: 7 elements sorted by increasing leading monomials #--- [1*x^4, 1*w^1*y^3+1073741826*x^1*z^3, 1*w^1*x^3, 1*t^1*z^1+1073741826, 1*w^2*x^2, 1*w^3*x^1, 1*w^4]: msolve-0.6.5/output_files/elim-31.res000066400000000000000000000005661456710632100174470ustar00rootroot00000000000000#Reduced Groebner basis data #--- #field characteristic: 1073741827 #variable order: t, w, x, y, z #monomial order: eliminating first variable, blocks: graded reverse lexicographical #length of basis: 7 elements sorted by increasing leading monomials #--- [1*w^1*y^3+1073741826*x^1*z^3, 1*x^4, 1*w^1*x^3, 1*w^2*x^2, 1*w^3*x^1, 1*w^4, 1*t^1*z^1+1073741826]: msolve-0.6.5/output_files/elim-qq.e2.res000066400000000000000000000002761456710632100201500ustar00rootroot00000000000000#Reduced Groebner basis data #--- #field characteristic: 0 #variable order: x, y, z #monomial order: graded reverse lexicographical #length of basis: 1 element #--- [x^4 ]: msolve-0.6.5/output_files/elim-qq.res000066400000000000000000000004311456710632100176340ustar00rootroot00000000000000#Reduced Groebner basis data #--- #field characteristic: 0 #variable order: w, x, y, z #monomial order: graded reverse lexicographical #length of basis: 6 elements sorted by increasing leading monomials #--- [w*y^3-1*x*z^3, x^4, w*x^3, w^2*x^2, w^3*x, w^4 ]: msolve-0.6.5/output_files/input-overflow-16.res000066400000000000000000000002011456710632100215060ustar00rootroot00000000000000[0, [65519, 2, 4, ['y', 'x'], [0, 1], [1, [[4, [0, 65375, 599, 21103, 1]], [0, [1]], [ [[3, [0, 39978, 62904, 51433]]] ]]]]]: msolve-0.6.5/output_files/kat6-31.res000066400000000000000000000043031456710632100173570ustar00rootroot00000000000000[0, [1073741827, 6, 32, ['x1', 'x2', 'x3', 'x4', 'x5', 'x6'], [0, 0, 0, 0, 0, 1], [1, [[32, [0, 305313024, 425877696, 441817934, 1048560509, 896280192, 103165548, 866100570, 881789066, 117019049, 298010449, 739640425, 546473727, 821051238, 803499748, 678925363, 236650704, 869619437, 511300299, 994688984, 226363686, 275554777, 457284933, 504063416, 422512237, 187137815, 763317831, 176681200, 611614347, 617747344, 473142393, 37675150, 1]], [0, [1]], [ [[31, [1073741826, 135200027, 303309998, 1010474949, 855264717, 284622213, 1015193218, 1001941651, 157682957, 366981127, 997084202, 112843258, 299643641, 732861002, 459038092, 1058946328, 904780998, 903053243, 955733229, 350886987, 503340552, 272980853, 914514770, 782023996, 681911430, 380182197, 785008187, 367872464, 950019599, 99103765, 611858126, 650769636]]], [[31, [0, 72383631, 67627534, 984247644, 840552191, 147407023, 435576954, 281894845, 748405377, 952791598, 745687351, 843391320, 571125957, 960455373, 817353032, 439135409, 191816458, 715772302, 357018661, 1061814754, 39660876, 832991532, 1057081960, 828795534, 368622185, 437214992, 853769875, 651539936, 437619982, 876301232, 930008500, 258775846]]], [[31, [0, 561569982, 164613167, 586257239, 981531943, 720509563, 92876848, 324405767, 1033540006, 594711203, 603364016, 282725444, 38414285, 1027805587, 412538255, 1046132356, 400474046, 590341335, 721346398, 61252735, 1028237959, 40441920, 360247302, 930749865, 675607806, 57908316, 460094088, 217736643, 590481071, 712988252, 501686397, 992506050]]], [[31, [0, 503272905, 660739003, 745903700, 661316402, 550594170, 372752605, 231578190, 308237836, 592232982, 592856772, 1027040452, 704253332, 721278227, 653351822, 522169477, 952757145, 325654121, 536234380, 990496782, 716437322, 861161314, 712997786, 570047944, 940799019, 1036631308, 13286819, 56926757, 268834442, 135310190, 250898123, 1073732849]]], [[31, [0, 405786210, 29107124, 936450337, 847063500, 49790878, 738680638, 271763113, 515329870, 361128221, 780775241, 1011646636, 146997346, 145255793, 34721499, 684315075, 150045506, 601060188, 591888514, 395346803, 111477221, 813269375, 633641048, 500620140, 895240756, 962508853, 964699692, 1037344086, 912409273, 910203011, 158961571, 570825918]]] ]]]]]: msolve-0.6.5/output_files/kat7-qq.res000066400000000000000000000670531456710632100175710ustar00rootroot00000000000000[0, [0, 7, 64, ['x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7'], [0, 0, 0, 0, 0, 0, 1], [1, [[64, [0, 228365353886946088684, -763373458670602961852, -359663845546219431368836, 3209385389138529302364288, 205846425950837062688656779, -2853641714056631320036315533, -51151764141609454210073816612, 1052511796632042603478207177984, 4576016243529733580325085768016, -191964235296019739299538617667960, 267930574387106011353199282576378, 16672108396758004845011203834138898, -64760192459383697244491423339086212, -213510767819712633128286403175349924, -2927880489525601298647457619258783252, -80612482942800175204026062154805311824, 1631787059858337673658221352246796630103, 3533252769643661041291371337648470396983, -176209278060185676650121484202241251790732, 637732908330012568565201918461964478144768, 5451391466492991967674097357227724958239368, -65703360128668260936381452728299517444020672, 481105874533976838867700887882053148168363648, -1488185479369924035255423940640729065524223056, -31390476221880528297478828821318629285492693760, 439028662041813222719967807524164711507660684800, -1711035117173976744601578673549925611127113559040, -9094646913448198704218611279383915103789735059456, 145195391542455286666694190775359363683629372059648, -868366745802275641961088482996182803153232080998400, 2715313205748288883928565989963705647309073277566976, 8092906632584637541850707732418937467131669162622976, -232304791705648504917906539765060800984750688572538880, 2195810938057512375613147954722046647346197874568724480, -11495456480286131995916241834297717379965644941400211456, 12104846296111873114297803163788239276683826176055181312, 387808835401096147746518628252389323259129613776518643712, -4178927855094574209975506906225158286252207288344985468928, 23537148835759883621268242204268959593986347780042026647552, -56089544872532549394720958047659370451858917572192268976128, -360967767890203016962761119445313732750442090721989653168128, 5139788846616217549517041177322162568017379723926719552290816, -31754975712161601207137884682405072377122920562716679509901312, 100181065351355238737522076400494781210021764572997602940813312, 147011413593912762059676437401109527419091587472528015123021824, -4024803610378969474660740926075588698831813728386778493813260288, 26806468629674683356775750549974455001121372528919998778465845248, -95226795878744709510191395780084895944438913199106668770573156352, 37818986336846606822907116738481234089520192106666758907235401728, 1842793382258942718854280372322800829957821190732828234777211437056, -12993601718214963488684845972455972771962268711466769139586056585216, 49057535840478166417399711420554781123828377398866787671526118260736, -77439566545398389737248813328854222915595352597704714227807619645440, -363743542325337433332220171741324438459197859419965396429295908290560, 3434705011422206727204815447690347324596560118256789902428522567172096, -13971631833688372841330553046271317884723991856584064872875820434063360, 27998093437233325593892713950199207948006316498713915335947396640145408, 22260052264380589696142408229044996639522599987033227320502854042517504, -359816821215394318629283495286731217705372907371625458667152150932488192, 1290141108175726161777004261740027862654019384427064517239049981251289088, -2680159653270848861109524784701653427240125897988046283434534023737638912, 3473421029550422212759980911329180954934990178556773755917055634387763200, -2627349827312801435389171831247858786383287278067803994346795579182415872, 892934857175667173353771846211005174359761166973411609221227824457711616]], [63, [228365353886946088684, -1526746917341205923704, -1078991536638658294106508, 12837541556554117209457152, 1029232129754185313443283895, -17121850284339787920217893198, -358062348991266179470516716284, 8420094373056340827825657423872, 41184146191767602222925771912144, -1919642352960197392995386176679600, 2947236318258166124885192108340158, 200065300761096058140134446009666776, -841882501971988064178388503408120756, -2989150749475976863796009644454898936, -43918207342884019479711864288881748780, -1289799727084802803264416994476884989184, 27740380017591740452189762988195542711751, 63598549853585898743244684077672467145694, -3347976283143527856352308199842583784023908, 12754658166600251371304038369239289562895360, 114479220796352831321156044501782224123026728, -1445473922830701740600391960022589383768454784, 11065435114281467293957120421287222407872363904, -35716451504878176846130174575377497572581353344, -784761905547013207436970720532965732137317344000, 11414745213087143790719162995628282499199177804800, -46197948163697372104242624185847991500432066094080, -254650113576549563718121115822749622906112581664768, 4210666354731203313334131532485421546825251789729792, -26051002374068269258832654489885484094596962429952000, 84174709378196955401785545688874875066581271604576256, 258973012242708401339222647437405998948213413203935232, -7666058126286400662290915812247006432496772722893783040, 74657571893955420770847030460549586009770727735336632320, -402340976810014619857068464200420108298797572949007400960, 435774466660027432114720913896376613960617742337986527232, 14348926909840557466621189245338404960587795709731189817344, -158799258493593819979069262436556014877583876957109447819264, 917948804594635461229461445966489424165467563421639039254528, -2243581794901301975788838321906374818074356702887690759045120, -14799678483498323695473205897257863042768125719601575779893248, 215871131557881137079715729447530827856729948404922221196214272, -1365463955622948851906929041343418112216285584196817218925756416, 4407966875459630504450971361621770373240957641211894529395785728, 6615513611726074292685439683049928733859121436263760680535982080, -185140966077432595834394082599477080146263431505791810715409973248, 1259904025594710117768460275848799385052704508859239942587894726656, -4570886202179746056489186997444075005333067833557120100987511504896, 1853130330505483734322448720185580470386489413226671186454534684672, 92139669112947135942714018616140041497891059536641411738860571852800, -662673687628963137922927144595254611370075704284805226118888885846016, 2550991863704864653704784993868848618439075624741072958919358149558272, -4104297026906114656074187106429273814526553687678349854073803841208320, -19642151285568221399939889274031519676796684408678131407181979047690240, 188908775628221369996264849622969102852810806504123444633568741194465280, -782411382686548879114510970591193801544543543968707632881045944307548160, 1595891325922299558851884695161354853036360040426693174149001608488288256, 1291083031334074202376259677284609805092310799247927184589165534466015232, -21229192451708264799127726221917141844617001534925902061361976905016803328, 77408466490543569706620255704401671759241163065623871034342998875077345280, -163489738849521780527681011866800859061647679777270823289506575447995973632, 215352103832126177191118816502409219205969391070519972866857449332041318400, -165523039120706490429517825368615103542147098518271651643848121488492199936, 57147830859242699094641398157504331159024714686298342990158580765293543424]], [ [[63, [-1598557477208622620788, -9155261346533689069912, 6174904356705282258550136, -47001648261697925889990016, -5638435011729923057064060579, 77791239202960890140981075922, 1959807065785352364765641835404, -39892113576522807886390866102730, -249708462767928908459564435789998, 9307638034002923061942209208416932, -7390235412241157998150022213263672, -1011199165886483594653841380983766210, 3929445709497654858231498927161951900, 21523711536787867424593227459129780198, 89478070922353791503160830297452113714, 6181420507667769767703102887917691414372, -114113840190873471030734661701741496069157, -403067782612724870352201088445522997097564, 14944956734772166480371031363043428863922580, -50918594865405704379960083095861814692032288, -555692518137465267930230767832305484576182224, 6706299382264745671073725929155607363647457072, -48049770256118661078407677458088952194740780672, 118334190509865146018844735046735067783494714944, 3658799417877664311854703218812806891876912928512, -49164586837343829874938546147715993467717451739136, 188691492022203975873585544606391537977032253028352, 1159394528931100485886504661262054853027071262187520, -18287355974638312375898173212491093028136402586714112, 110931692376215467480389398778313715811439746176188416, -338116269810130071533886713620187699089553882488061952, -1284028420640551353791918132355613752956677056599654400, 33046665193901221659162380955492044117903375761259888640, -311526000387248968256694225974187139867659260233934831616, 1633308154886254472989896927882719895514785207832690556928, -1416694591377833068279469069526224558912734257822819680256, -61303962606099641462953129393738887236364503460570750517248, 654957594342387611404015515802920044774683535614542430076928, -3681363021142379230029671030288308226383348590222531587211264, 8342575869620506339382458830864116199929848109774033362354176, 64111438385552526107324240032104487024438480874507524978507776, -876550910279644403497683106820244424878745845583314826089725952, 5383535078997466668218726617469420555438185933553137441371586560, -16636044221177546610247763689254579165924160445459047218187075584, -30806714644174988104918281788634898856899025877924170314266181632, 739206838892664378330043398351530199322864419380074503433623699456, -4897859462067463905843395951424314151477366531646078005220151918592, 17316912716124756024822527861510710908900490377573090586417717837824, -4463691688469813420177969131863687143595282892809216111561607741440, -364077948087003990288272495561413642212575090973677410509471545819136, 2548184303227756946643531238465654861249262278252583477863911631355904, -9621043608786321912906781197118622271081897466776915795985643222335488, 14789996047031576608321998478008735805022578281039812376046338802974720, 77429473023042123068198411195743001043249617196933120824203075198648320, -719481091832532826388801216936425962903752075055818147962398876924641280, 2940717086258433986795198237001979879668886666355370165679357439992922112, -5890614535361200021169564922472571223900613804600385925598616509225107456, -5268277497498287678872185149606457408791329701412427447260078599611351040, 80265464816463347396564991023878943962365006335263737048719321909579218944, -289185771241960416928868225660839129420423339827651001864794194164687306752, 605789400236845491775418680963482308503217202816837594474410129288022982656, -792194134037973101017666583194535056220013629162853886639925778461906436096, 604677789027432259579637251801524731494179487328361127939651574716101033984, -207343671948894758526080084234552457595539898619733269295945135735862984704]], 7], [[63, [0, -610017903713478884292, 106217823104924364732684, -146493411458584875645906, -128242987547567061406160148, 1317496411187916451413722328, 51761019924111488551059665406, -840712737533185442995450844622, -7928662198508663610248711508252, 205785211481791723852340993138538, 248231631145734426375063376588998, -21389792911239425772866353896526908, 4542528500236282937336140153957182, 410255449389606923712330154860044946, 14285719627519030253861778437832663240, 92477950158635075119084367225024415180, -3117153740214217600854143672761115129274, -4941275650496981800825065834791616322692, 286832758745568121737137242907514314651712, -510248337463828597175584716086214735367296, -10914263618245376629348686445062082981549056, 66729085506314949261913480250230216301464608, -491608997877851509758669330842329808975492832, 1828571244339303911431159420940456210638947648, 60973210327153894792091358194691508452500328192, -751409014460494264563558045537541316713210212096, 1318086610238334022255004129112495800123990525952, 32991001029019392311247136356458279535239498121216, -308196039590376232312260373108220475947853093365760, 1152190328657903119092681907511852096444053865447424, 1305636508999971719792447370146520921850591161188352, -60857501548001368187879792289915344384237611570741248, 617784592423519323601682701476270685521653507574005760, -3699607307411576075236627684949962338064503805379739648, 7765423767416509982862156520723485638490105424242671616, 94422388266103121650865143289213871832922402263549870080, -1237220432498125177621344253128486843740164392373680340992, 7898932634790131291300928508360031673129571903255706861568, -26420836726742884830160813810626850691980215204329715400704, -53345782536622824264940752479953756757173075502801941954560, 1493327909746385291332346667836744342977723897024740235149312, -11697570578456763626594258317616749467683719393214159376089088, 51610897794106850790177779493386498170867102220616537886162944, -54492133204485176324625216923868581462487588351465711722299392, -1181955052490815341440302302527691990405005056420601776966729728, 11177725085196238544691195672102612671957769003915235327242928128, -53558617161857979212589829962435080143312299584279459134061936640, 107386197447891418459359870985563785220705507080974170493519134720, 519914196759812710576847976971624901430107134998568634873827819520, -5995113933558914284879500811223970190448323370699721769118997676032, 29726147423384854533330444369312858148347054986366708186213001461760, -78904577921566966639910501242549914571332008280745253152827264466944, -45510172020366167000512543418442181213445342328509633582414281310208, 1661127079810046492661677089226252037518518057159842695277141553053696, -9012599206885719191315353415989971765104451907524707922685293999685632, 25746236788421023815426877903012868775964679965154018943903708808740864, -19826139541074290350239066796441785515395612198359627094245729789542400, -175239578244578197746720946025421363348242143418205918459816945987354624, 935805478043839409520634997109067550240293980683348733794257646942945280, -2563509323358946748160917054009545082646299512186752569282492605906550784, 4503585116109613490644224179209416239843938910037329499014209539183476736, -5133246235989907245179388275573398959520656487770297455675316754446286848, 3494386840966612365456202883477650060498942579721230276965047243485741056, -1087051130474725254517635291039484560090144029358935872095407786296344576]], 1], [[63, [0, -2299767584498825234688, 101480304377789527518060, 4928029375698286899968244, -294333513499739008862958810, 4824993028645027801386414, 196259933026331985156970560180, -2214278109720540407845576627620, -47553219510460174706442303867600, 990816958185640064675007617222586, 2613612196360486752526128100749876, -172907602907438404774794335362649742, 718505879864787114729672969814398204, 10059532039422841147641091420689932484, -114530665167608111301512811813922193544, 894997622512183737387359842221358778730, -965724959938682298649312932647073316674, -163465666355145445322234679133181123473848, 1682228681628477744541570118037017342239716, 2815992374416973536720519728282380234262984, -144763082077280988199038513447820090846682448, 1055137672968757462221621437850270131772548280, -2171235232045917045511292175426415549094728752, -52690029919485659245376203884132709533795217632, 850482572667364806164725065685340288062153675392, -4996045507102262308954994483753249677592381397504, -10477411567521799464172125766497270621189253575168, 383353598758524470826944057245782173879254854632448, -2905207226975572602317688484116570550427558456131584, 9472086028516251815784366959250248359051880501907456, 38151137678053170442038368974465588105209740788506624, -861676292879937679917046062000306848075718749734993920, 7375589987897961599206365423255734025756199979845386240, -34874131977942982124253177363009548073569363087106637824, 2863037642828441860352422771855620570061440323657269248, 1589890784493291791851805144869416799384282297223870939136, -15946203665829219958995814830499391485846681888177430986752, 86392202297598931386151224090025715423767291378379601739776, -153483542423132682840842682108630423930623359464215968481280, -2004297560774548576342627024370548603442623956291714646278144, 23363584032574673602161322595725543945548404835207970692268032, -130510355638518898748268173860737241887401374550516157741268992, 326100518105475642845924433781369368685674075559682885371822080, 1384380070737482901238578955760517317653675506193213087115378688, -20620205017470070391633576977223560555740102888553988442776666112, 120807958010074788337888896462619491228132269159003659741075341312, -364929420326615830660127399469046551636265327508461860524157566976, -301241635166293697246138110392903191224480124867794871307988893696, 10381212481419769414939125053729765168838884226953992482227893567488, -64352163702520268331505202269786022643880625508381318685782177742848, 220447374622902032386501410810405448290457391490393313517701995429888, -220873048896761285764109409938686579060740717826244046126284852428800, -2436458739755130426858230611767377010910945424966917152480310239166464, 17937250891815734686810109515461492615712486504525810424065732305223680, -66436449436748852959771822711096258338430628716441648222907913021161472, 127576802570888578722089268474632386282791831336985273990033859527311360, 96878709176654248145571687264729607718649338580516040028745588138835968, -1706976992767948421597532756537427777146004014901081429821694982737625088, 6916231546865885621625800615368539965346954275648821936023427696960733184, -17487806649549060468256787971434539287490828868744925993747860135748829184, 30343206421634253997382890233489175707287747803126636701566619065996279808, -35466121109446560620301270421861908679687164315993949210115371860058177536, 25329619232461449691339358347002235602242927416624162001355430406324748288, -8375420603356871544034712919068400520393782295922026760259355138162950144]], 7], [[63, [0, 33926396647165892098, 4499335505712813190044, -124668376849232421650607, -2555889490021313847041502, -95970727881422305899865647, 6304229045767035659010073398, 33091988080983888046091730085, -3425623912101394456305070753497, 9027472883127577828757477652315, 650142131384969526291352635875140, -1775110073136772710734500965965607, -48663210897349647236349794562755352, -797374327981441605432551350982150415, 6628820767398668057026957719874151943, 247860407949874238964310200867617337228, -2306977965450158019427742128012321975928, -22078510942920046794678270443376403086564, 356165213906388169031645399697455239139592, -412819747228935872791284462213005086964976, -18841380797118635295581534128444170406806192, 183622388705869179019645518596552482321121280, -974585138753104093273352821043005412933863104, -3846519650821829615083688754746882115451354176, 149790102780123105816684341163977054678292296832, -1144184845277697347852651733976666416718918501632, -1190952555253564156883728024913009133836002025472, 78696557704030404130394475403672880284429693249536, -528532162977750720402653043475391665552561538617344, 450801256851736567948740505800447393245471389851648, 17007543631037897361800157198721347194839157236801536, -150341091660228749010679916011488052801576151376740352, 701402127679230992200305608752550666412941221969330176, -963842448474816637474402847004002605431163257755271168, -20164160063309818358102378564192781032870685874735546368, 243746421049613195297325361056040595418478391955938082816, -1431901875872913275797594626668467014466945595301755879424, 3150234236835654839929849092514986844840809840617752363008, 24036948079985722754304481960591170281446609419562163109888, -300128633817066200767626703591945702900958337935369645850624, 1712410209899757798415697090919904227928391949419772125380608, -5023169887429139961233077343766140922306966650149847137517568, -9521191512394608433190873047818744621955737148359967323979776, 217567861555182504085660559472851392434026150857392813760315392, -1401538398757304079577693481448587091130801945561621975491674112, 4991472750330304208648113615347820711086152510973501004232785920, -4617879556917646963562198269542499689205224805029783626833723392, -72876430706434033896704330730519042298225141233125145566137810944, 627984103631885501484850350848835597209909483693967926527921225728, -2959107379153132712248288200550569562870916007212069170582634102784, 7651614551990028619533483938029008327066184820513008932523465506816, 2410700772709824893919242101291085532540807251411338936562825035776, -119300988573643871654673450457501150565557954822585498124000446906368, 653635404444060975776131349714243501709528522015573141506168312561664, -2732771830908840305923701273904268379934946831704002646299334479446016, 9728286672784773894965286007416995271171100579076266121811704087052288, -19679466584602733385039577709706367284277329620596273026605401975554048, -38208753531927758405792468523571928514254033171679201100113334650273792, 461617288369515316401130209624988472348109742213902708427828641656733696, -1774579201129870336620384897359789190313534607449048136146443989604630528, 3972518937459023293803919204939428862515528259599463276238028519744995328, -5484137877223835026109326084058601295218670572192274932605710320072130560, 4365150947900532242480189728982051775715025669509997412690108339776913408, -1544756869621977993261902782003478059075467831194277291925053170000068608]], 1], [[63, [0, -69418122170675020081320, 167080401056555547987990, 113010876634562466956102946, -911080367844916115617313181, -66790513048527299985716840097, 829939181123936151994722118152, 18082508647517816062746470735433, -314305568969361714882240773920329, -2210764886166196455345513398536494, 60825335988343422526561797763082415, 52978790389894580778396926696526405, -6160652314713143454016320609644474982, 11748342189986574766793652347353191405, 241288520410651455830096996513288777205, 72821481788509392110345022955355906280, 11929699934134936722850065329166718878264, -306272788942540134040326448898982246194574, -1298066899302172355328478798730129877653958, 41357467874757172951210551301073916730799388, -74399071133336331185015395460264699593464180, -2161157756313213408379503669890459491701084024, 14819659249189058697195723836963276512912750896, -26233361286680834193293709790966712402842093248, -254935665453660155769678054967537389360454967424, 6427516051247784787413757401978054292788837634560, -64544068655065332833490280853951809822659335522304, 124649742135781707792994633077793927364965481235456, 3136657965339354195464882437585466071340302625777664, -31114361897674074149593168099566501540589880778719232, 95610527030529509814681013986293749479628182127828992, 491439804676629063583556461740958860837312110310604800, -7332981192202976575309474282214446961057525136190439424, 43396825533443229368485939129014253855895078568046755840, -108542022685424717319927794782568433499852046718373724160, -679322150426698319214137113671281216336501385109366112256, 9924783224415423618015923058851321849871016202715501428736, -58054241052916117774785025174100800764055839845668321492992, 126291883253660734533796499129796006302911662225807063908352, 890953835512429306240916134622790914958363312948084826177536, -10475455569257786755388543389980904689364883594236507566637056, 49364050012528708114602398941101835542952948887785713044553728, -46783845411315049419799381490951081710716431106656118648078336, -1060510230894477013759266676635849914071592614208877242974470144, 8182940634692298455795011514838851919849653717821826288377135104, -22725901614301531978945103813345702492183055767246949678493728768, -75009692483753445452188442243494079322883613056597429929834971136, 1012052543801412119671294406398363940777645860363047797783569367040, -4303453473047010027441500434078318282916855916969037353916752199680, 3684368598823371852072570159637332775811935714844877291104243810304, 72703337815391906216043025254678921376247865233475568202509191217152, -578183238779383669142767393888278296236492002745358162767453259563008, 2267586468369730152321503500552283246738410569485947013202652610691072, -1899210000549363861104241466937353812864782351759563876773401412501504, -34905948410037465914103123940215126740107773770367354580773109223129088, 228743807812544067439239940328937396839007617455155390375892166796902400, -642279923474075350268986787390091905461571874530550996032862711699210240, 161648841295202760988129565199450702161671273694334994653466122812129280, 5802196530456706126992048646919385749610940297212647296871617464675336192, -24512397170738373807623303574096982142730714610226048735477080797764124672, 54641813194624791418622709187401719311267831466519605309284983674496876544, -73808212314534502355050153426190857648698786080561735029180668765863411712, 57409481280641755171540319810461419263138220591699316246561538219773526016, -19917629940878663822692912926592223593832126350646367045379016486301990912]], 7], [[63, [0, -2148192267934874797194, -3322647823300105060524, 2300731034148459590198907, -1432970157870803465682966, -821244178804814042974957797, -108947493667149274778450610, 95770726204931215052814941421, 1351983812444205991520622293277, 2774586003771884998629354180273, -540756141186625418650057392164442, -1706868487147646141997630239173701, 94887093908766703043467903344650256, 531645497643627440697094680413235465, -12779454147378662668927712404225964667, -131762258884293165010211548815598934496, 2008047324014411102718337926442192498734, 14422569368146210638896258148721611109740, -253916622728427717548975481476736142404432, -198295316823476380422687428851767145539072, 15456987804859893725936070028036923249648912, -83042861254305753931203595558796511641964576, 318226435025173042169969679759963055415237664, 2973161296061980937320101097149836765470166976, -105275886323621550668987470055728869389758626816, 719710236494587814802661199393377614347079101184, 3528141470915748632086921348128151683113004607488, -76440003375031649541349931635209604720303408419840, 331977635365999677228559463938243882274998788360192, 1508732280545715422414051261801349868084517535977472, -25833712586647209882919229870101588634207776542375936, 136713993943408710963512659262063091881471233574977536, -111693725294486365064050425655196866584473599055364096, -4429558128484180179669617505448391209219009082209271808, 46127026216242252601755288083354073719450288184845008896, -251576567342814624909399019018098013582907931116888653824, 394780549225858283258928121187039714474338916415625494528, 7048658331359153681522999680676343328960311542717761978368, -81099365169435701462099540410927983255444787521985959690240, 449987420117752365311063629677748534348413440160482463842304, -880299466112364328028837705812018268449262061800427960139776, -8709457970749653792957404982317790715996784579007362384265216, 103126315162363407859175799607178216820841842924107710548934656, -558182923161437894973115507100415452046722146902654416320462848, 1249347010481586926824506751113155956740091293775283826450235392, 6795857510318920467014523726661470183784850778629999341835649024, -86633501971172092302182799105247558015171767731048959492403232768, 456756615258589393068690166723024709867360085898814157806106574848, -1100250897889932252403951791677550015025722551774500750375608385536, -3010502446357235558920129920107626510632488231955323934849512767488, 44268136765742571755452568020921684691452773400954640560660301217792, -228716933499736958130602896953198404025496910383554551159287367860224, 595965565085559651165729848931169417222231857198306314007072976404480, 536323047274038038669719766636140847745771253562286443400153689751552, -13202589386912360872103231958530728821000534487959346814238145791393792, 63864657991747404222173078455302521810017981522980172652150178107621376, -147994361883391328287419627081266172113110938077399893855868054981836800, -31013137919465924186366026581676669265418068251795857400817383114801152, 1533447362203884785908051344246330963291476053144451973499498451592806400, -5910904980239190069623236370690547498071995248775653852460796656528392192, 12696812404963378646039354087629751653539126512995355193679611542277980160, -16822274494041426386058588759564749861040310070192899829235676969307209728, 12943997565696779802345657669442913651779473271004758875042971608758091776, -4462630956685714202756608036898936615106907067894578843339042491111309312]], 1] ]]]]]: msolve-0.6.5/output_files/kat8-qq-truncate.res000066400000000000000000000015261456710632100214060ustar00rootroot00000000000000#Truncated reduced Groebner basis data #--- #field characteristic: 0 #variable order: x1, x2, x3, x4, x5, x6, x7, x8 #monomial order: graded reverse lexicographical #length of basis: 5 elements sorted by increasing leading monomials #--- [x1+2*x2+2*x3+2*x4+2*x5+2*x6+2*x7+2*x8-1, 15*x5^2+30*x4*x6+64*x5*x6+51*x6^2+30*x3*x7+64*x4*x7+102*x5*x7+144*x6*x7+95*x7^2+30*x2*x8+64*x3*x8+102*x4*x8+144*x5*x8+190*x6*x8+240*x7*x8+147*x8^2-1*x2-4*x3-9*x4-16*x5-25*x6-36*x7-49*x8, 30*x4*x5+30*x3*x6-34*x5*x6-36*x6^2+30*x2*x7-34*x4*x7-72*x5*x7-114*x6*x7-80*x7^2-60*x2*x8-94*x3*x8-132*x4*x8-174*x5*x8-220*x6*x8-270*x7*x8-192*x8^2+x2+4*x3+9*x4+16*x5+25*x6+36*x7+64*x8, x4^2+2*x3*x5+2*x2*x6-4*x2*x7-4*x3*x7-4*x4*x7-4*x5*x7-4*x6*x7-4*x7^2+2*x2*x8-4*x7*x8+x7, 2*x3*x4+2*x2*x5-4*x2*x6-4*x3*x6-4*x4*x6-4*x5*x6-4*x6^2+2*x2*x7-4*x6*x7+2*x3*x8-4*x6*x8+x6 ]: msolve-0.6.5/output_files/mq_2_1.res000066400000000000000000000001061456710632100173440ustar00rootroot00000000000000[0, [251, 1, 1, ['x'], [1], [1, [[1, [159, 1]], [0, [1]], [ ]]]]]: msolve-0.6.5/output_files/multy-16.res000066400000000000000000000001551456710632100176700ustar00rootroot00000000000000[0, [65521, 2, 3, ['x', 'y'], [0, 1], [1, [[3, [0, 65520, 0, 1]], [0, [1]], [ [[2, [0, 0, 65520]]] ]]]]]: msolve-0.6.5/output_files/multy-31.res000066400000000000000000000001741456710632100176660ustar00rootroot00000000000000[0, [1073741827, 2, 3, ['x', 'y'], [0, 1], [1, [[3, [0, 1073741826, 0, 1]], [0, [1]], [ [[2, [0, 0, 1073741826]]] ]]]]]: msolve-0.6.5/output_files/multy-qq.res000066400000000000000000000001551456710632100200630ustar00rootroot00000000000000[0, [0, 2, 3, ['x', 'y'], [0, 1], [1, [[3, [0, -1, 0, 1]], [2, [-1, 0, 3]], [ [[2, [0, 0, -2]], 1] ]]]]]: msolve-0.6.5/output_files/nf-16.res000066400000000000000000000004761456710632100171270ustar00rootroot00000000000000[39314*x3^2+13107*x2^1*x4^1+39319*x3^1*x4^1+39318*x4^2+13105*x2^1*x5^1+52422*x3^1*x5^1+39323*x4^1*x5^1+39318*x5^2+13104*x2^1+52416*x3^1+52415*x4^1+52415*x5^1, 26206*x3^2+52412*x2^1*x4^1+26200*x3^1*x4^1+26202*x4^2+52418*x2^1*x5^1+13101*x3^1*x5^1+26200*x4^1*x5^1+26206*x5^2+52417*x2^1+13105*x3^1+13106*x4^1+13105*x5^1]: msolve-0.6.5/output_files/nf-31.res000066400000000000000000000006361456710632100171220ustar00rootroot00000000000000[858993463*x3^2+644245099*x2^1*x4^1+858993468*x3^1*x4^1+858993467*x4^2+644245097*x2^1*x5^1+429496736*x3^1*x5^1+858993472*x4^1*x5^1+858993467*x5^2+644245096*x2^1+429496730*x3^1+429496729*x4^1+429496729*x5^1, 214748363*x3^2+429496726*x2^1*x4^1+214748357*x3^1*x4^1+214748359*x4^2+429496732*x2^1*x5^1+644245093*x3^1*x5^1+214748357*x4^1*x5^1+214748363*x5^2+429496731*x2^1+644245097*x3^1+644245098*x4^1+644245097*x5^1]: msolve-0.6.5/output_files/nf-8.res000066400000000000000000000003661456710632100170460ustar00rootroot00000000000000[62*x3^2+23*x2^1*x4^1+67*x3^1*x4^1+66*x4^2+21*x2^1*x5^1+86*x3^1*x5^1+71*x4^1*x5^1+66*x5^2+20*x2^1+80*x3^1+79*x4^1+79*x5^1, 38*x3^2+76*x2^1*x4^1+32*x3^1*x4^1+34*x4^2+82*x2^1*x5^1+17*x3^1*x5^1+32*x4^1*x5^1+38*x5^2+81*x2^1+21*x3^1+22*x4^1+21*x5^1]: msolve-0.6.5/output_files/nf-lm-bug.res000066400000000000000000000000651456710632100200560ustar00rootroot00000000000000[1*a^3, 2*a^3+2*a^1+99*c^1, 99*c^2+4*a^1+100*c^1+5]: msolve-0.6.5/output_files/nonradical_radicalshape-31.res000066400000000000000000000001661456710632100233270ustar00rootroot00000000000000[0, [1073741827, 3, 3, ['x', 'y', 'A'], [-33,97,92], [1, [[1, [0, 1]], [0, [1]], [ [[-1, [0]]], [[-1, [0]]] ]]]]]: msolve-0.6.5/output_files/nonradical_radicalshape-no-square-31.c0.res000066400000000000000000000000001456710632100255230ustar00rootroot00000000000000msolve-0.6.5/output_files/nonradical_radicalshape-no-square-qq.p3.res000066400000000000000000000001171456710632100257520ustar00rootroot00000000000000[0, [1, [[[-3 / 2^2, -5 / 2^3], [-3 / 2^2, -5 / 2^3], [5 / 2^3, 3 / 2^2]]] ]]: msolve-0.6.5/output_files/nonradical_radicalshape-no-square-qq.res000066400000000000000000000002761456710632100254370ustar00rootroot00000000000000[0, [0, 4, 8, ['x', 'y', 'z', 'A'], [30/256,-17/256,-5/256,-13/256], [1, [[1, [2957511, 3454087]], [0, [3454087]], [ [[0, [2186132]], 1], [[0, [2325791]], 1], [[0, [-2480426]], 1] ]]]]]: msolve-0.6.5/output_files/nonradical_radicalshape-qq.p3.res000066400000000000000000000000371456710632100240430ustar00rootroot00000000000000[0, [1, [[[3, 3], [1, 1]]] ]]: msolve-0.6.5/output_files/nonradical_radicalshape-qq.res000066400000000000000000000001321456710632100235160ustar00rootroot00000000000000[0, [0, 2, 6, ['y', 'x'], [0, 1], [1, [[1, [-3, 1]], [0, [1]], [ [[0, [-1]], 1] ]]]]]: msolve-0.6.5/output_files/nonradical_shape-31.res000066400000000000000000000011131456710632100220000ustar00rootroot00000000000000[0, [1073741831, 5, 11, ['x1', 'x2', 'x3', 'x4', 'A'], [-33,97,92,98,-35], [1, [[8, [806088589, 773290875, 392047488, 448660708, 158395478, 796667501, 603542507, 839056289, 1]], [0, [1]], [ [[7, [469066563, 872087359, 789792069, 653598341, 610549694, 461793855, 822207508, 424465292]]], [[7, [1012630728, 518320180, 397734047, 582252170, 175855446, 823918569, 370262236, 364408665]]], [[7, [490926065, 926842152, 356918246, 830759452, 836862130, 786699753, 119267664, 1014874695]]], [[7, [1028528857, 28102185, 545211281, 584060027, 779823490, 573635187, 521548435, 1853246]]] ]]]]]: msolve-0.6.5/output_files/nonradical_shape-qq.p1024.res000066400000000000000000000106771456710632100227620ustar00rootroot00000000000000[0, [1, [[[-121722272026806639175856903448929079302848245474621385201239705897079472942038956314423425753112602377323173273174623183253070934886329550162115952343737243158086979185162746275824177474560982414644740502255844544648901616361099177697297175384973010766534875461537061482054482628866692571871217860524253137660670103 / 2^1024, -60861136013403319587928451724464539651424122737310692600619852948539736471019478157211712876556301188661586636587311591626535467443164775081057976171868621579043489592581373137912088737280491207322370251127922272324450808180549588848648587692486505383267437730768530741027241314433346285935608930262126568830335051 / 2^1023], [252984634308875205806967596955718077650558918408715819253084888140725924207082192196031120855505004873563811770654313903159684496722108827746523775474053335182918310694389344612271370978919546452867868777549561023444186404465571443864425337398327435421017000697036246972830310025928915784766084100646684762102406757 / 2^1023, 505969268617750411613935193911436155301117836817431638506169776281451848414164384392062241711010009747127623541308627806319368993444217655493047550948106670365836621388778689224542741957839092905735737555099122046888372808931142887728850674796654870842034001394072493945660620051857831569532168201293369524204813515 / 2^1024], [1974753744297339254025542889635096362532383855582341518499522801642374084092110859263964427763533465989029469814452603178688540020753960481831921556427738414024151152302576007040120358917118165579307881644576209105210581038098050471546721436117420459659492440224046057894899482864113381959777192895928395858673591553 / 2^1024, 987376872148669627012771444817548181266191927791170759249761400821187042046055429631982213881766732994514734907226301589344270010376980240915960778213869207012075576151288003520060179458559082789653940822288104552605290519049025235773360718058710229829746220112023028947449741432056690979888596447964197929336795777 / 2^1023], [-3, -3]], [[-65946776567189173308463791314550679060514238197722953762121359525721425764476816206246764790070165228287805761540034837261745823231546705424489243590117516786791623576835067380395712341152547760636865023948941016162693794851872877342273302565388379528143334071356846733364736644378183743054708096075307763 / 2^1024, -32973388283594586654231895657275339530257119098861476881060679762860712882238408103123382395035082614143902880770017418630872911615773352712244621795058758393395811788417533690197856170576273880318432511974470508081346897425936438671136651282694189764071667035678423366682368322189091871527354048037559839 / 2^1023], [-976434721123226505829959295622471547128772173042666550777182348965573572943925576572744954142290126412635795925734930525994379525905190223455177042746744148721275222152516444738639658604653068683104229270574330448102814021442607119102781064944928325191222110264282830107289798785360545935287908224501472799 / 2^1023, -1952869442246453011659918591244943094257544346085333101554364697931147145887851153145489908284580252825271591851469861051988759051810380446910354085493488297442550444305032889477279317209306137366208458541148660896205628042885214238205562129889856650382444220528565660214579597570721091870575816449002163779 / 2^1024], [321735349979092056071196413455408702842642175907938024499421590846487747068461943467316687181611847322868069770397756517757875846614515385221138211645398979989090022582791465178986175480062912788922513185252059726596404049346172981314775742053400061584087154664979930053715269576007006096859060836237397995 / 2^1023, 643470699958184112142392826910817405685284351815876048998843181692975494136923886934633374363223694645736139540795513035515751693229030770442276423290797959978180045165582930357972350960125825577845026370504119453192808098692345962629551484106800123168174309329959860107430539152014012193718121672477847361 / 2^1024], [107861588091738954463758311447341484017078618736538394364058048694639605483300577879625086393444521612672068327922836014595273861288649973495708458383684474626660736054919291165781331760747656471671849771251003461302890409405477728884347866324496342298010306410751778943968347563087829782901213797774534482329 / 2^1024, 53930794045869477231879155723670742008539309368269197182029024347319802741650288939812543196722260806336034163961418007297636930644324986747854229191842237313330368027459645582890665880373828235835924885625501730651445204702738864442173933162248171149005153205375889471984173781543914891450606898887267241165 / 2^1023]]] ]]: msolve-0.6.5/output_files/nonradical_shape-qq.res000066400000000000000000000007471456710632100222120ustar00rootroot00000000000000[0, [0, 4, 18, ['x1', 'x2', 'x3', 'x4'], [0, 0, 0, 1], [1, [[4, [-9, 3, 8, 17, 5]], [3, [3, 16, 51, 20]], [ [[3, [-1482814286602093677141, 988542638259789810687, 988542578445336685687, 2471358263210272159703]], 729980468750000], [[3, [1232738891496063441669, -821825860583780645483, -821825947741983770483, -2054564712986826509027]], 145996093750000], [[3, [7296357631087314445713, -4864238186321243499466, -4864238670177444671341, -12160596416621204429554]], 221405029296875] ]]]]]: msolve-0.6.5/output_files/one-16.res000066400000000000000000000000061456710632100172720ustar00rootroot00000000000000[-1]: msolve-0.6.5/output_files/one-31.res000066400000000000000000000000061456710632100172670ustar00rootroot00000000000000[-1]: msolve-0.6.5/output_files/one-qq.g2.res000066400000000000000000000002741456710632100200030ustar00rootroot00000000000000#Reduced Groebner basis data #--- #field characteristic: 0 #variable order: x, y, z #monomial order: graded reverse lexicographical #length of basis: 1 element #--- [1 ]: msolve-0.6.5/output_files/one-qq.res000066400000000000000000000000061456710632100174650ustar00rootroot00000000000000[-1]: msolve-0.6.5/output_files/radical_shape-31.res000066400000000000000000000003471456710632100212750ustar00rootroot00000000000000[0, [1073741827, 3, 4, ['x', 'y', 'z'], [0, 0, 1], [1, [[4, [1073741826, 1073741826, 1073741826, 1073741826, 1]], [0, [1]], [ [[3, [1073741820, 1073741822, 1073741824, 1073741825]]], [[3, [1, 1073741826, 1, 1073741826]]] ]]]]]: msolve-0.6.5/output_files/radical_shape-qq.res000066400000000000000000000002461456710632100214710ustar00rootroot00000000000000[0, [0, 3, 4, ['x', 'y', 'z'], [0, 0, 1], [1, [[4, [-1, -1, -1, -1, 1]], [3, [-1, -2, -3, 4]], [ [[3, [-22, -24, -17, -56]], 1], [[3, [-7, -4, -9, -1]], 1] ]]]]]: msolve-0.6.5/output_files/realroot-extract.p256.res000066400000000000000000000042551456710632100222710ustar00rootroot00000000000000[0, [1, [[[0, 1 / 2^256], [519917134689817603033657631268209116893594431418786718786796295190792299532838017448719672487237 / 2^256, 519917134689817603033657631268209116893594431418786718786796295190795074362771255667154139299959 / 2^256], [-122680776115122206535372896123735420078981053427312491540840002588575571029431163791927 / 2^255, -122680776115122206535372896123735420078981053427312491540840002588575034723503174008697 / 2^255]], [[3296230464788315386465869935756989972355760245748239886080472022217939618589888573 / 2^298, 1648115232394157693232934967878494986177880122874119943040236011108969809294944287 / 2^297], [32494820909635121088607613285802912314138975534102185360308903650070386143175589848297296049441 / 2^252, 129979283638540484354430453143211649256555902136408741441235614600281544572702359550920004339755 / 2^254], [-67812225174093121439711693877270570394571799646342425291773948374865826809868144295091 / 2^256, -67812225174093121439711693877270570394571799646342425291773948374865826809868144158935 / 2^256]], [[83320342010616637375018851338091380349471783619758808078571159924293651331279773563688461069450776257613299589972936420113425 / 2^352, 41660171005308318687509425669045690174735891809879404039285579962146825665639886781844230534725388128806649794986468210056713 / 2^351], [1463310469298716819488079044281 / 2^256, 731655234649358409744039522143 / 2^255], [248149751416945626749997415309406611312722995309269984290337356519393903204494483933561 / 2^255, 496299502833891253499994830618813222625445990618539968580674713038787806408988967867123 / 2^256]], [[5207521378411890839043616221456297941275009067969364617947894695831914780531912586473830872887405930177318775542475475991533 / 2^348, 20830085513647563356174464885825191765100036271877458471791578783327659122127650345895323491549623720709275102169901903966133 / 2^350], [370527478527594184219066093639221611522810352038736490063496860442483 / 2^256, 185263739263797092109533046819610805761405176019368245031748430221277 / 2^255], [17145704655330412261616220319033754699151768858797688388601995476914741549234308519263 / 2^253, 137165637242643298092929762552270037593214150870381507108815963815317932393874468154105 / 2^256]]] ]]: msolve-0.6.5/output_files/realroot-extract.res000066400000000000000000000025561456710632100216000ustar00rootroot00000000000000[0, [1, [[[0, 1 / 2^150], [381974784202244349956839665734594332521749789580664219171 / 2^126, 1527899136808977399827358662938377330748570168253796449417 / 2^128], [-721052796389099865046191244931999226158987442995 / 2^128, -180263199097274966261547811232999806475814212091 / 2^126]], [[4843375362958734771737638256911840593766119 / 2^169, 9686750725917469543475276513823681187532239 / 2^170], [1527899136410321228355934202787899588177206065462058856331 / 2^128, 763949568205160614177967101393949794088603348192669712147 / 2^127], [-199282219022088440686162039481640237511048719929 / 2^128, -199282219022088440686162039481640237511048583773 / 2^128]], [[7651764948598497941042677560217312276625073805751735950393124280925106370292304800339 / 2^219, 244856478355151934113365681926953992852002361784055550412579976989603403849353753610849 / 2^224], [-1 / 2^127, 1 / 2^127], [729246577371436297993831230214579549053117663821 / 2^127, 1458493154742872595987662460429159098106235327643 / 2^128]], [[3825882476318418394412977397948182036518089701588174161591327117631060314986098459487 / 2^218, 61214119621094694310607638367170912584289435225410786585461233882096965039777575351793 / 2^222], [544441197292016749493457892849 / 2^127, 136110299323004187373364473221 / 2^125], [100773394816041478750500991846530653114714285805 / 2^126, 403093579264165915002003967386122612458857143221 / 2^128]]] ]]: msolve-0.6.5/output_files/reals_dim0-swapvar.p256.res000066400000000000000000000001031456710632100224560ustar00rootroot00000000000000[0, [1, [[[1, 1], [-2, -2], [3, 3]], [[1, 1], [2, 2], [3, 3]]] ]]: msolve-0.6.5/output_files/reals_dim0-swapvar.res000066400000000000000000000001031456710632100217630ustar00rootroot00000000000000[0, [1, [[[1, 1], [-2, -2], [3, 3]], [[1, 1], [2, 2], [3, 3]]] ]]: msolve-0.6.5/output_files/reals_dim0.p256.res000066400000000000000000000027071456710632100210110ustar00rootroot00000000000000[0, [1, [[[36509357909062631536129668436573070012487487067100583303001175658946635606055 / 2^255, 4563669738632828942016208554571633751560935883387572912875146957368329450757 / 2^252], [36509357909062631536129668436573070012487487067100583303001175658946635606055 / 2^256, 4563669738632828942016208554571633751560935883387572912875146957368329450757 / 2^253], [-60490684797868661441895377475208744393359927205523538345094237255746825568573 / 2^258, -483925478382949291535163019801669955146879417644188306760753898045974604548583 / 2^261]], [[1, 1], [0, 0], [0, 0]], [[3278955798161077339921616998930436909728483733114914607048732943254033559905 / 2^253, 26231646385288618719372935991443495277827869864919316856389863546032268479285 / 2^256], [6557911596322154679843233997860873819456967466229829214097465886508067119813 / 2^255, 13115823192644309359686467995721747638913934932459658428194931773016134239637 / 2^256], [63328796466738957984825113025800917297614244935801930326677856915848592681411 / 2^257, 126657592933477915969650226051601834595228489871603860653355713831697185362823 / 2^258]], [[2412335192444087404657728854347664746943124680534178417488699666831523534165 / 2^252, 38597363079105398474523661669562635951089994888546854679819194669304376546651 / 2^256], [-1 / 2^255, 1 / 2^255], [617557809265686375592378586713002175217439918216749674877107114708870024746325 / 2^260, 308778904632843187796189293356501087608719959108374837438553557354435012373163 / 2^259]]] ]]: msolve-0.6.5/output_files/reals_dim0.res000066400000000000000000000015371456710632100203160ustar00rootroot00000000000000[0, [1, [[[107291359935630315248585097660753910587 / 2^127, 26822839983907578812146274415188477647 / 2^125], [107291359935630315248585097660753910587 / 2^128, 26822839983907578812146274415188477647 / 2^126], [-355532291286331190123863132844989723573 / 2^131, -1422129165145324760495452531379958894291 / 2^133]], [[1, 1], [0, 0], [0, 0]], [[38543940173343311950004019810003894311 / 2^127, 77087880346686623900008039620007788667 / 2^128], [9635985043335827987501004952500973579 / 2^126, 4817992521667913993750502476250486791 / 2^125], [93053303113782607831679264095876317083 / 2^128, 372213212455130431326717056383505268333 / 2^130]], [[7089215977519551322153637654828504405 / 2^124, 113427455640312821154458202477256070491 / 2^128], [-1 / 2^127, 1 / 2^127], [1814839290245005138471331239636097127765 / 2^132, 907419645122502569235665619818048563883 / 2^131]]] ]]: msolve-0.6.5/output_files/xy-qq.res000066400000000000000000000001301456710632100173420ustar00rootroot00000000000000[0, [0, 2, 1, ['x', 'y'], [0, 1], [1, [[1, [0, 1]], [0, [1]], [ [[0, [0]], 1] ]]]]]: msolve-0.6.5/src/000077500000000000000000000000001456710632100136235ustar00rootroot00000000000000msolve-0.6.5/src/crt/000077500000000000000000000000001456710632100144135ustar00rootroot00000000000000msolve-0.6.5/src/crt/longlong.h000066400000000000000000001110721456710632100164050ustar00rootroot00000000000000/* 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)) #define NEED_CLZ_TAB #if !(GMP_LIMB_BITS == 32 && defined (__arm__)) #if !(GMP_LIMB_BITS == 64 && defined (__ia64)) #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 #if !(GMP_LIMB_BITS == 32 && defined (__arm__)) #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 #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) #if !((GMP_LIMB_BITS == 64 && defined (__ia64)) || \ (GMP_LIMB_BITS == 32 && defined (__arm__))) #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 #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) /* MIPS and ARM - Use clz builtins */ #if (defined (__mips__) || defined (__arm__)) #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; \ int __sgn1 = 0, __sgn2 = 0; \ if ((n1) & __highbit) \ { \ __n0 = -(n0); \ __n1 = ~(n1) + (__n0 == 0); \ __sgn1 = ~__sgn1; \ } else \ { \ __n0 = (n0); \ __n1 = (n1); \ } \ if ((d) & __highbit) \ { \ __d = -(d); \ __sgn2 = ~__sgn2; \ } else \ { \ __d = (d); \ } \ udiv_qrnnd((q), (r), (mp_limb_t) __n1, (mp_limb_t) __n0, (mp_limb_t) __d); \ if (__sgn1 ^ __sgn2) \ { \ (q) = -(q); \ if (!__sgn2) \ { \ (q)--; \ (r) = (__d) - (r); \ } \ } else if (__sgn1 && __sgn2) \ { \ (q)++; \ (r) = (__d) - (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__)) #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 #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 msolve-0.6.5/src/crt/mpq_reconstruct.c000066400000000000000000000161451456710632100200160ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ /** This implementation is a (very) slight modification of the functions in FLINT. **/ #include /* #define ROT(u,v,t) \ */ /* do { mpz _t = *u; *u = *v; *v = *t; *t = _t; } while (0); */ static inline void ROT(mpz_t u, mpz_t v, mpz_t t){ mpz_swap(u, v); mpz_swap(v, t); } int _mpq_reconstruct_mpz_2(mpz_t n, mpz_t d, const mpz_t a, const mpz_t m, const mpz_t N, const mpz_t D) { mpz_t q, r, s, t; int success = 0; /* Quickly identify small integers */ if (mpz_cmp(a, N) <= 0) { mpz_set(n, a); mpz_set_ui(d, 1); return 1; } mpz_sub(n, a, m); if(mpz_cmp_ui(n, 0)>=0){ if(mpz_cmp(n, N) <= 0){ mpz_set_ui(d, 1); return 1; } } else{ mpz_neg(n, n); if(mpz_cmp(n, N) <= 0){ mpz_set_ui(d, 1); mpz_neg(n, n); return 1; } } /* if (fmpz_cmpabs(n, N) <= 0) */ /* { */ /* fmpz_one(d); */ /* fprintf(stderr, "ici?\n"); */ /* return 1; */ /* } */ mpz_init(q); mpz_init(r); mpz_init(s); mpz_init(t); mpz_set(r, m); mpz_set_ui(s, 0); mpz_set(n, a); mpz_set_ui(d, 1); while (mpz_cmpabs(n, N) > 0) { mpz_fdiv_q(q, r, n); mpz_mul(t, q, n); mpz_sub(t, r, t); ROT(r, n, t); mpz_mul(t, q, d); mpz_sub(t, s, t); ROT(s, d, t); } if (mpz_sgn(d) < 0) { mpz_neg(n, n); mpz_neg(d, d); } if (mpz_cmp(d, D) <= 0) { mpz_gcd(t, n, d); if(mpz_cmp_ui(t, 1)==0){ success = 1; } else{ success = 0; } } mpz_clear(q); mpz_clear(r); mpz_clear(s); mpz_clear(t); return success; } int mpq_reconstruct_mpz_2(mpq_t res, const mpz_t a, const mpz_t m, const mpz_t N, const mpz_t D) { return _mpq_reconstruct_mpz_2(mpq_numref(res), mpq_denref(res), a, m, N, D); } int _mpq_reconstruct_mpz(mpz_t n, mpz_t d, const mpz_t a, const mpz_t m) { mpz_t N; int result; mpz_init(N); mpz_fdiv_q_2exp(N, m, 1); mpz_sqrt(N, N); result = _mpq_reconstruct_mpz_2(n, d, a, m, N, N); mpz_clear(N); return result; } int _mpq_reconstruct_mpz_with_denom(mpz_t n, mpz_t d, const mpz_t a, const mpz_t m, mpz_t num, mpz_t den) { // mpz_t N; int result; // mpz_init(N); // mpz_fdiv_q_2exp(N, m, 1); // mpz_sqrt(N, N); result = _mpq_reconstruct_mpz_2(n, d, a, m, num, den); // mpz_clear(N); return result; } int mpq_reconstruct_mpz(mpq_t *res, mpz_t a, const mpz_t m) { if(mpz_cmp_ui(a, 0)>=0){ return _mpq_reconstruct_mpz(mpq_numref(*res), mpq_denref(*res), a, m); } else{ while(mpz_cmp_ui(a, 0) < 0){ // mpz_fprint(stderr, a); fprintf(stderr, "\n"); mpz_add(a, a, m); } int b = _mpq_reconstruct_mpz(mpq_numref(*res), mpq_denref(*res), a, m); return b; } } int mpq_reconstruct_mpz_with_denom(mpq_t *res, mpz_t a, const mpz_t m, mpz_t num, mpz_t den) { if(mpz_cmp_ui(a, 0)>=0){ return _mpq_reconstruct_mpz_with_denom(mpq_numref(*res), mpq_denref(*res), a, m, num, den); } else{ while(mpz_cmp_ui(a, 0) < 0){ mpz_add(a, a, m); } int b = _mpq_reconstruct_mpz_with_denom(mpq_numref(*res), mpq_denref(*res), a, m, num, den); return b; } } /* Rational reconstruction -- classical algorithm returns 1 in case of success else returns 0 assumes that 2ND < mod In case of success, n and d are such that n/d = u modulo mod gcd(n,d)=1 and |n| < recadata->N, |d| < recdata->D */ int ratreconwden(mpz_t n, mpz_t d, /* output numerator and denominator */ mpz_t u, const mpz_t mod, const mpz_t gden, rrec_data_t recdata){ /* while(mpz_cmp_ui(u, 0) < 0){ */ /* mpz_add(u, u, mod); */ /* } */ mpz_mod(u, u, mod); mpz_set(recdata->r0, mod); mpz_set_ui(recdata->t0, 0); mpz_set(recdata->r1, u); mpz_mul(recdata->r1, recdata->r1, gden); mpz_mod(recdata->r1, recdata->r1, mod); mpz_set_ui(recdata->t1, 1); while(mpz_cmp(recdata->r1, recdata->N)>0){ mpz_fdiv_q(recdata->q, recdata->r0, recdata->r1); mpz_mul(recdata->tmp, recdata->q, recdata->r1); mpz_sub(recdata->tmp, recdata->r0, recdata->tmp); mpz_swap(recdata->r0, recdata->r1); mpz_swap(recdata->r1, recdata->tmp); mpz_mul(recdata->tmp, recdata->q, recdata->t1); mpz_sub(recdata->tmp, recdata->t0, recdata->tmp); mpz_swap(recdata->t0, recdata->t1); mpz_swap(recdata->t1, recdata->tmp); } mpz_set(n, recdata->r1); mpz_set(d, recdata->t1); if(mpz_sgn(d) < 0){ mpz_neg(n, n); mpz_neg(d, d); } mpz_gcd(recdata->q, n, d); if(mpz_cmp(d, recdata->D) <= 0 && mpz_cmp_ui(recdata->q, 1)==0){ return 1; } return 0; } /* Rational reconstruction -- classical algorithm returns 1 in case of success else returns 0 assumes that 2ND < mod In case of success, n and d are such that n/d = u modulo mod gcd(n,d)=1 and |n| < recadata->N, |d| < recdata->D */ int ratrecon(mpz_t n, mpz_t d, /* output numerator and denominator */ mpz_t u, const mpz_t mod, rrec_data_t recdata){ while(mpz_cmp_ui(u, 0) < 0){ mpz_add(u, u, mod); } mpz_set(recdata->r0, mod); mpz_set_ui(recdata->t0, 0); mpz_set(recdata->r1, u); mpz_set_ui(recdata->t1, 1); while(mpz_cmp(recdata->r1, recdata->N)>0){ mpz_fdiv_q(recdata->q, recdata->r0, recdata->r1); mpz_mul(recdata->tmp, recdata->q, recdata->r1); mpz_sub(recdata->tmp, recdata->r0, recdata->tmp); mpz_swap(recdata->r0, recdata->r1); mpz_swap(recdata->r1, recdata->tmp); mpz_mul(recdata->tmp, recdata->q, recdata->t1); mpz_sub(recdata->tmp, recdata->t0, recdata->tmp); mpz_swap(recdata->t0, recdata->t1); mpz_swap(recdata->t1, recdata->tmp); } mpz_set(n, recdata->r1); mpz_set(d, recdata->t1); if(mpz_sgn(d) < 0){ mpz_neg(n, n); mpz_neg(d, d); } mpz_gcd(recdata->q, n, d); if(mpz_cmp(d, recdata->D) <= 0 && mpz_cmp_ui(recdata->q, 1)==0){ return 1; } return 0; } msolve-0.6.5/src/crt/mpz_CRT_ui.c000066400000000000000000000040721456710632100165750ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ /** This implementation is a (very) slight modification of the functions in FLINT. **/ #include "ulong_extras.h" void _mpz_CRT_ui_precomp(mpz_t out, const mpz_t r1, const mpz_t m1, uint64_t r2, uint64_t m2, mp_limb_t m2inv, const mpz_t m1m2, mp_limb_t c, int sign) { mp_limb_t r1mod, s; mpz_t tmp; mpz_init(tmp); if (mpz_sgn(r1) < 0) mpz_add(tmp, r1, m1); else mpz_set(tmp, r1); r1mod = mpz_fdiv_ui(tmp, m2); s = n_submod(r2, r1mod, m2); s = n_mulmod2_preinv(s, c, m2, m2inv); mpz_addmul_ui(tmp, m1, s); if (sign) { mpz_sub(out, tmp, m1m2); if (mpz_cmpabs(tmp, out) <= 0) mpz_swap(out, tmp); } else { mpz_swap(out, tmp); } mpz_clear(tmp); } /** returns out s.t. 0 < out < m1 x m2 (if sign=0) or -(m1 x m2) / 2 < out < (m1 x m2) / 2 out mod m1 = r1 and out mod m2 = r2 **/ void mpz_CRT_ui(mpz_t out, const mpz_t r1, const mpz_t m1, uint64_t r2, uint64_t m2, const mpz_t m1m2, mpz_t tmp, int sign) { mp_limb_t c; c = mpz_fdiv_ui(m1, m2); c = n_invmod(c, m2); if (c == 0) { fprintf(stderr, "Exception (fmpz_CRT_ui). m1 not invertible modulo m2.\n"); exit(1); } _mpz_CRT_ui_precomp(out, r1, m1, r2, m2, n_preinvert_limb(m2), m1m2, c, sign); } msolve-0.6.5/src/crt/ulong_extras.h000066400000000000000000000050601456710632100172770ustar00rootroot00000000000000/* 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 "longlong.h" #if FLINT64 #define UWORD_MAX_PRIME UWORD(18446744073709551557) #else #define UWORD_MAX_PRIME UWORD(4294967291) #endif #define UWORD_HALF (UWORD_MAX / 2 + 1) static __inline__ double n_precompute_inverse(ulong n) { return (double) 1 / (double) n; } static __inline__ ulong n_preinvert_limb(ulong n) { ulong norm, ninv; count_leading_zeros(norm, n); invert_limb(ninv, n << norm); return ninv; } /* ulong n_ll_mod_preinv(ulong a_hi, ulong a_lo, */ /* ulong n, ulong ninv); */ #include "ulong_extras/ll_mod_preinv.c" static __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); } static __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); } static __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); } static __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); } static __inline__ ulong n_negmod(ulong x, ulong n) { /* FLINT_ASSERT(x < n); */ /* FLINT_ASSERT(n != 0); */ return n_submod(0, x, n); } /* static __inline__ ulong n_gcdinv(ulong * a, ulong x, ulong y); */ #include "ulong_extras/gcdinv.c" static __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; } #endif msolve-0.6.5/src/fglm/000077500000000000000000000000001456710632100145505ustar00rootroot00000000000000msolve-0.6.5/src/fglm/Makefile.am000066400000000000000000000006251456710632100166070ustar00rootroot00000000000000noinst_LTLIBRARIES = libfglm.la libfglm_la_SOURCES = fglm_core.c libfglm_ladir = $(includedir)/msolve/fglm libfglm_la_HEADERS = fglm.h libfglm_la_CFLAGS = $(SIMD_FLAGS) $(CPUEXT_FLAGS) $(OPENMP_CFLAGS) EXTRA_DIST = fglm.h \ libfglm.h \ berlekamp_massey.c \ data_fglm.c \ fglm_core.c \ inner-product.c \ matrix-mult.c \ linalg-fglm.c msolve-0.6.5/src/fglm/berlekamp_massey.c000066400000000000000000000434171456710632100202500ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ /* Copyright (C) 2019 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (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_VERSION >= 3 # include #endif //#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_modif( 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_modif( 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_modif( 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_modif( 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_modif( 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_modif( 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_modif( 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_modif( 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; } //shift ne sert pas int nmod_em_gcd(nmod_berlekamp_massey_t B, long shift){ slong i, l, k, queue_len, queue_lo, queue_hi; queue_lo = B->npoints; // vaut 0 en entree queue_hi = B->points->length; //vaut 2*dim ou dim est la dimension du quotient 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; // nmod_poly_fprint_pretty(stderr, B->R0, "x");fprintf(stderr, "\n"); /* Ri = Ri * x^queue_len + Vi*rt */ //R0 vaut x^queue_len-1 avec queue_len = 2*dim - 1 nmod_poly_shift_left(B->R0, B->R0, queue_len); nmod_poly_mul(B->qt, B->V0, B->rt); 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; } //shift ne sert pas int nmod_em_gcd_preinstantiated(nmod_berlekamp_massey_t B, long shift){ slong l, k, queue_len, queue_lo, queue_hi; queue_lo = B->npoints; // vaut 0 en entree queue_hi = B->points->length; //vaut 2*dim ou dim est la dimension du quotient queue_len = queue_hi - queue_lo + shift; FLINT_ASSERT(queue_len >= 0); //On a deja fait ce job de maniere appropriee avant l'appel. /* 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; // nmod_poly_fprint_pretty(stderr, B->R0, "x");fprintf(stderr, "\n"); /* Ri = Ri * x^queue_len + Vi*rt */ //R0 vaut x^queue_len-1 avec queue_len = 2*dim - 1 nmod_poly_shift_left(B->R0, B->R0, queue_len); nmod_poly_mul(B->qt, B->V0, B->rt); 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; } /* return 1 if reduction changed the master poly, 0 otherwise */ int nmod_berlekamp_massey_reduce_modif( 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; // fprintf(stderr, "queue_len = %ld, queue_hi = %ld, queue_lo=%ld\n", queue_len, queue_hi, queue_lo); // nmod_poly_fprint_pretty(stderr, B->R0, "x");fprintf(stderr, "\n"); /* Ri = Ri * x^queue_len + Vi*rt */ //R0 vaut x^queue_len nmod_poly_shift_left(B->R0, B->R0, queue_len); // nmod_poly_fprint_pretty(stderr, B->R0, "x");fprintf(stderr, "\n"); //done. nmod_poly_mul(B->qt, B->V0, B->rt); 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; } msolve-0.6.5/src/fglm/data_fglm.c000066400000000000000000000162221456710632100166350ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include #include #include #include #include #include #include static inline void free_sp_mat_fglm(sp_matfglm_t *mat){ if(mat!=NULL){ free(mat->dense_mat); free(mat->triv_idx); free(mat->triv_pos); free(mat->dense_idx); free(mat->dst); free(mat); } } static inline fglm_data_t *allocate_fglm_data(szmat_t nrows, szmat_t ncols, szmat_t nvars){ fglm_data_t * data = malloc(sizeof(fglm_data_t)); szmat_t block_size = nvars; //taille de bloc dans data->res if(posix_memalign((void **)&data->vecinit, 32, ncols*sizeof(CF_t))){ fprintf(stderr, "posix_memalign failed\n"); exit(1); } if(posix_memalign((void **)&data->res, 32, 2 * block_size * ncols * sizeof(CF_t))){ fprintf(stderr, "posix_memalign failed\n"); exit(1); } if(posix_memalign((void **)&data->vecmult, 32, nrows*sizeof(CF_t))){ fprintf(stderr, "posix_memalign failed\n"); exit(1); } if(posix_memalign((void **)&data->vvec, 32, ncols*sizeof(CF_t))){ fprintf(stderr, "posix_memalign failed\n"); exit(1); } data->pts = calloc(ncols * 2, sizeof(mp_limb_t)); for(szmat_t i = 0; i < 2*block_size*ncols; i++){ data->res[i] = 0; } for(szmat_t i = 0; i < nrows; i++){ data->vecmult[i] = 0; } for(szmat_t i = 0; i < ncols; i++){ data->vvec[i] = 0; data->vecinit[i] = 0; } return data; } static inline void free_fglm_data(fglm_data_t *data){ free(data->vecinit); free(data->res); free(data->vecmult); free(data->vvec); free(data->pts); free(data); } static inline void display_fglm_matrix(FILE *file, sp_matfglm_t *matrix){ fprintf(file, "%u\n", matrix->charac); fprintf(file, "%u\n", matrix->ncols); fprintf(file, "%u\n", matrix->nrows); szmat_t len1 = (matrix->ncols)*(matrix->nrows); for(szmat_t i = 0; i < len1; i++){ fprintf(file, "%d ", matrix->dense_mat[i]); } fprintf(file, "\n"); szmat_t len2 = (matrix->ncols) - (matrix->nrows); for(szmat_t i = 0; i < len2; i++){ fprintf(file, "%d ", matrix->triv_idx[i]); } fprintf(file, "\n"); for(szmat_t i = 0; i < len2; i++){ fprintf(file, "%d ", matrix->triv_pos[i]); } fprintf(file, "\n"); for(szmat_t i = 0; i < matrix->nrows; i++){ fprintf(file, "%d ", matrix->dense_idx[i]); } fprintf(file, "\n"); } static inline void display_fglm_colon_matrix(FILE *file, sp_matfglmcol_t *matrix){ fprintf(file, "%u\n", matrix->charac); fprintf(file, "%u\n", matrix->ncols); fprintf(file, "%u\n", matrix->nrows); fprintf(file, "%u\n", matrix->nzero); szmat_t len1 = (matrix->ncols)*(matrix->nrows); for(szmat_t i = 0; i < len1; i++){ fprintf(file, "%d ", matrix->dense_mat[i]); } fprintf(file, "\n"); szmat_t len2 = (matrix->ncols) - (matrix->nrows); for(szmat_t i = 0; i < len2; i++){ fprintf(file, "%d ", matrix->triv_idx[i]); } fprintf(file, "\n"); for(szmat_t i = 0; i < len2; i++){ fprintf(file, "%d ", matrix->triv_pos[i]); } fprintf(file, "\n"); for(szmat_t i = 0; i < matrix->nrows; i++){ fprintf(file, "%d ", matrix->dense_idx[i]); } fprintf(file, "\n"); for(szmat_t i = 0; i < matrix->nzero; i++){ fprintf(file, "%d ", matrix->zero_idx[i]); } fprintf(file, "\n"); } static inline param_t *allocate_fglm_param(mp_limb_t prime, long nvars){ param_t *param = malloc(sizeof(param_t)); if(param==NULL){ fprintf(stderr, "Pb when calling malloc to allocate param_t\n"); exit(1); return param; } param->charac = prime; param->nvars = nvars; nmod_poly_init(param->elim, prime); nmod_poly_init(param->denom, prime); param->coords = malloc(sizeof(nmod_poly_t) * (nvars-1)); for(nvars_t i = 0; i < nvars-1; i++){ nmod_poly_init(param->coords[i], prime); } return param; } static inline void free_fglm_param(param_t *param){ nmod_poly_clear(param->elim); nmod_poly_clear(param->denom); for(szmat_t i = 0; i < param->nvars-1; i++){ nmod_poly_clear(param->coords[i]); } free(param->coords); free(param); } static inline fglm_bms_data_t *allocate_fglm_bms_data(szmat_t dim, mp_limb_t prime){ fglm_bms_data_t * data_bms = (fglm_bms_data_t *)malloc(sizeof(fglm_bms_data_t)); nmod_poly_init(data_bms->A, prime); nmod_poly_init(data_bms->B, prime); nmod_poly_init(data_bms->Z1, prime); nmod_poly_init2(data_bms->rZ1, prime, dim+1); nmod_poly_init(data_bms->Z2, prime); nmod_poly_init2(data_bms->rZ2, prime, dim+1); nmod_poly_init2(data_bms->V, prime, dim+1); nmod_poly_init2(data_bms->param, prime, dim+1); for(len_t i = 0; i < dim + 1; i++){ data_bms->rZ1->coeffs[i] = 0; data_bms->rZ2->coeffs[i] = 0; data_bms->V->coeffs[i] = 0; data_bms->param->coeffs[i] = 0; } nmod_berlekamp_massey_init(data_bms->BMS, (mp_limb_t)prime); nmod_poly_factor_init(data_bms->sqf); return data_bms; } static inline void nmod_poly_set_prime(nmod_poly_t poly, mp_limb_t prime){ mp_limb_t ninv = n_preinvert_limb(prime); poly->mod.n = prime; poly->mod.ninv = ninv; #if __FLINT_VERSION < 3 count_leading_zeros(poly->mod.norm, prime); #else poly->mod.norm = flint_clz(prime); #endif } static inline void fglm_param_set_prime(param_t *param, mp_limb_t prime){ param->charac = prime; nmod_poly_set_prime(param->elim, prime); nmod_poly_set_prime(param->denom, prime); for(nvars_t i = 0; i < param->nvars-1; i++){ nmod_poly_set_prime(param->coords[i], prime); } } static inline void fglm_bms_data_set_prime(fglm_bms_data_t *data_bms, mp_limb_t prime){ nmod_poly_set_prime(data_bms->A, prime); nmod_poly_set_prime(data_bms->B, prime); nmod_poly_set_prime(data_bms->Z1, prime); nmod_poly_set_prime(data_bms->rZ1, prime); nmod_poly_set_prime(data_bms->Z2, prime); nmod_poly_set_prime(data_bms->rZ2, prime); nmod_poly_set_prime(data_bms->V, prime); nmod_poly_set_prime(data_bms->param, prime); nmod_berlekamp_massey_set_prime(data_bms->BMS, prime); } static inline void free_fglm_bms_data(fglm_bms_data_t *data_bms){ nmod_poly_clear(data_bms->A); nmod_poly_clear(data_bms->B); nmod_poly_clear(data_bms->Z1); nmod_poly_clear(data_bms->Z2); nmod_poly_clear(data_bms->rZ1); nmod_poly_clear(data_bms->rZ2); nmod_poly_clear(data_bms->V); nmod_poly_clear(data_bms->param); nmod_poly_factor_clear(data_bms->sqf); nmod_berlekamp_massey_clear(data_bms->BMS); free(data_bms); } msolve-0.6.5/src/fglm/fglm.h000066400000000000000000000046651456710632100156610ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Vincent Neiger * Mohab Safey El Din */ param_t *nmod_fglm_compute(sp_matfglm_t *, mod_t, nvars_t, szmat_t, nvars_t *, uint32_t *, nvars_t*, int, md_t *); param_t *nmod_fglm_guess_colon(sp_matfglmcol_t *, const mod_t, CF_t *, CF_t **, const nvars_t, const nvars_t, nvars_t *, uint32_t *, nvars_t *, int, md_t *); param_t *nmod_fglm_compute_trace_data(sp_matfglm_t *, mod_t, szmat_t, szmat_t, szmat_t, nvars_t *, uint32_t *, nvars_t*, int, fglm_data_t **, fglm_bms_data_t **, int *, md_t *); int nmod_fglm_compute_apply_trace_data(sp_matfglm_t *, const mod_t, param_t *, const long, const long, const long, nvars_t *, uint32_t *, nvars_t*, fglm_data_t *, fglm_bms_data_t *, const long, const int, md_t *); void display_fglm_param(FILE *, param_t *); void display_fglm_param_maple(FILE *, param_t *); void display_nmod_poly(FILE *, nmod_poly_t); msolve-0.6.5/src/fglm/fglm_core.c000066400000000000000000002133161456710632100166570ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include /* for timing functions */ #include "../neogb/tools.h" #ifdef _OPENMP #include #else double omp_get_wtime(void) { return realtime();} #endif #define MIN(x, y) ((x) > (y) ? (y) : (x)) #define DEBUGFGLM 0 #define BLOCKWIED 0 #include #include "../msolve/msolve-data.h" #include "libfglm.h" #include "data_fglm.c" #include "linalg-fglm.c" #include "matrix-mult.c" #include "berlekamp_massey.c" #ifdef BLOCKWIED #include #include #include #include "../upolmat/nmod_mat_extra.h" #include "../upolmat/nmod_mat_left_nullspace.c" #include "../upolmat/nmod_mat_permute_rows.c" #include "../upolmat/nmod_mat_poly.h" #include "../upolmat/nmod_mat_poly_mem.c" #include "../upolmat/nmod_mat_poly_set_from.c" #include "../upolmat/nmod_mat_poly_arith.c" #include "../upolmat/nmod_mat_poly_mbasis.c" #include "../upolmat/nmod_mat_poly_shift.c" #include "../upolmat/nmod_poly_mat_utils.h" #include "../upolmat/nmod_poly_mat_utils.c" #include "../upolmat/nmod_poly_mat_pmbasis.h" #include "../upolmat/nmod_poly_mat_pmbasis.c" #endif void display_nmod_poly(FILE *file, nmod_poly_t pol){ fprintf(file, "[%ld,\n", pol->length-1); if(pol->length != 0){ fprintf(file, "["); for(long i = 0; i < pol->length - 1 ; i++){ fprintf(file, "%lu, ", pol->coeffs[i]); } fprintf(file, "%lu]", pol->coeffs[pol->length - 1]); } else{ fprintf(file, "[0]"); } fprintf(file, "]"); } void display_fglm_param(FILE * file, param_t *param){ fprintf(file, "%ld,\n", param->charac); fprintf(file, "%d,\n", param->nvars); display_nmod_poly(file, param->elim); fprintf(file, ",\n"); display_nmod_poly(file, param->denom); fprintf(file, ",\n"); fprintf(file, "["); for(int c = param->nvars-2; c >= 0; c--){ display_nmod_poly(file, param->coords[c]); fprintf(file, "\n"); } fprintf(file, "]"); } void display_fglm_param_maple(FILE * file, param_t *param){ fprintf(file, "[%ld, \n", param->charac); fprintf(file, "%d, \n", param->nvars); display_nmod_poly(file, param->elim); fprintf(file, ", \n"); display_nmod_poly(file, param->denom); fprintf(file, ", \n"); for(int c = param->nvars-2; c > 0; c--){ display_nmod_poly(file, param->coords[c]); fprintf(file, ", \n"); } display_nmod_poly(file, param->coords[0]); fprintf(file, "]:\n"); } /* Points of B are u_0, .., u_l */ /* They become u_l, ..., u_0 */ static inline void mirror_points(nmod_berlekamp_massey_t B, szmat_t length){ CF_t tmp; szmat_t mid = length / 2; for(szmat_t i = 0; i < mid; i++){ tmp = B->points->coeffs[i]; B->points->coeffs[i] = B->points->coeffs[length - i - 1]; B->points->coeffs[length - i - 1] = tmp; } } #if 0 static inline void mirror_poly(nmod_poly_t out, nmod_poly_t in){ szmat_t mid = in->length / 2; for(long i = 0; i <= mid; i++){ out->coeffs[i] = in->coeffs[in->length - i - 1]; out->coeffs[in->length - i - 1] = in->coeffs[i]; } out->length=in->length; } #endif static inline void mirror_poly_solve(nmod_poly_t out, nmod_poly_t in, szmat_t length){ long i; long m = MIN(in->length, length); if(out->alloc < length){ nmod_poly_fit_length(out, length); } out->length=length; for(i = 0; i < m; i++){ out->coeffs[length - 1 - i] = in->coeffs[i]; } for(;icoeffs[length-1-i] = 0; } } static inline void mirror_poly_inplace(nmod_poly_t in){ CF_t tmp; szmat_t mid = in->length / 2; for(long i = 0; i < mid; i++){ tmp = in->coeffs[i]; in->coeffs[i] = in->coeffs[in->length - i - 1]; in->coeffs[in->length - i - 1] = tmp; } } /* U is a Hankel matrix of size dim returns 0 when U is not invertible else it returns 1. */ static int invert_hankel_matrix(fglm_bms_data_t *data_bms, szmat_t deg){ nmod_poly_one(data_bms->BMS->R0); nmod_poly_zero(data_bms->BMS->R1); nmod_poly_zero(data_bms->BMS->V0); nmod_poly_one(data_bms->BMS->V1); szmat_t dim = deg; //B->points->length / 2; data_bms->BMS->npoints = 0; data_bms->BMS->points->length = 2 * dim - 1; mirror_points(data_bms->BMS, data_bms->BMS->points->length); nmod_em_gcd(data_bms->BMS, 0); if(data_bms->BMS->R1->length-1 < dim-1 && dim > 1){ fprintf(stderr, "Singular matrix\n"); return 0; } if(data_bms->BMS->V1->coeffs[0]!=0){ //Compute Z1 = LC(R1)^{-1} * V1 mp_limb_t inv = n_invmod(data_bms->BMS->R1->coeffs[data_bms->BMS->R1->length-1], (data_bms->BMS->R1->mod).n); nmod_poly_scalar_mul_nmod(data_bms->Z1, data_bms->BMS->V1, inv); mirror_points(data_bms->BMS, data_bms->BMS->points->length); nmod_poly_one(data_bms->BMS->R0); //x^(2dim -1) nmod_poly_zero(data_bms->BMS->R1); nmod_poly_zero(data_bms->BMS->V0); nmod_poly_one(data_bms->BMS->V1); data_bms->BMS->npoints = 0; //(R_i, R_{i+1}, V_i, V_{i+1}) = EMGCD(R_0, R_1) nmod_em_gcd(data_bms->BMS, 0); //Z2 = LC(R_{i+1})^{-1} x (V_{i+1}) inv = n_invmod(data_bms->BMS->R1->coeffs[data_bms->BMS->R1->length-1], (data_bms->BMS->R1->mod).n); nmod_poly_scalar_mul_nmod(data_bms->Z2, data_bms->BMS->V1, inv); } else{//V1(0) = 0 fprintf(stderr, "Warning: this part of the code has not been tested intensively\n"); nmod_poly_one(data_bms->BMS->R0); nmod_poly_zero(data_bms->BMS->R1); nmod_poly_zero(data_bms->BMS->V0); nmod_poly_one(data_bms->BMS->V1); data_bms->BMS->npoints = 0; data_bms->BMS->points->length = 2 * dim + 1; long queue_lo = (data_bms->BMS->npoints); long queue_len = (data_bms->BMS->points->length) - queue_lo; nmod_poly_zero(data_bms->BMS->rt); nmod_poly_set_coeff_ui(data_bms->BMS->rt, queue_len+1, 1); for (long i = 0; i < queue_len; i++) { nmod_poly_set_coeff_ui(data_bms->BMS->rt, queue_len - i, data_bms->BMS->points->coeffs[queue_lo + i]); } nmod_poly_set_coeff_ui(data_bms->BMS->rt, 0, 1); nmod_em_gcd_preinstantiated(data_bms->BMS, 0);//B->rt is pre-instantied if(data_bms->BMS->R1->length-1 == dim){ mp_limb_t inv = n_invmod(data_bms->BMS->R1->coeffs[data_bms->BMS->R1->length-1], (data_bms->BMS->R1->mod).n); nmod_poly_scalar_mul_nmod(data_bms->Z1, data_bms->BMS->V1, inv); nmod_poly_set_coeff_ui(data_bms->BMS->rt, queue_len+1, 1); for (long i = 0; i < queue_len; i++) { nmod_poly_set_coeff_ui(data_bms->BMS->rt, i + 1, data_bms->BMS->points->coeffs[queue_lo + i]); } nmod_poly_set_coeff_ui(data_bms->BMS->rt, 0, 1); nmod_poly_one(data_bms->BMS->R0); //x^(2dim +1) nmod_poly_zero(data_bms->BMS->R1); nmod_poly_zero(data_bms->BMS->V0); nmod_poly_one(data_bms->BMS->V1); data_bms->BMS->npoints = 0; //(R_i, R_{i+1}, V_i, V_{i+1}) = EMGCD(R_0, R_1) nmod_em_gcd_preinstantiated(data_bms->BMS, 0); //Z2 = LC(R_{i+1})^{-1} x (V_{i+1}) inv = n_invmod(data_bms->BMS->R1->coeffs[data_bms->BMS->R1->length-1], (data_bms->BMS->R1->mod).n); nmod_poly_scalar_mul_nmod(data_bms->Z2, data_bms->BMS->V1, inv); fprintf(stderr, "Something should be checked\n"); return 1; } else{ nmod_poly_one(data_bms->BMS->R0); nmod_poly_zero(data_bms->BMS->R1); nmod_poly_zero(data_bms->BMS->V0); nmod_poly_one(data_bms->BMS->V1); data_bms->BMS->npoints = 0; data_bms->BMS->points->length = 2 * dim + 1; queue_lo = (data_bms->BMS->npoints); queue_len = (data_bms->BMS->points->length) - queue_lo; nmod_poly_zero(data_bms->BMS->rt); nmod_poly_set_coeff_ui(data_bms->BMS->rt, queue_len+1, data_bms->BMS->R1->mod.n - 1); for (long i = 0; i < queue_len; i++) { nmod_poly_set_coeff_ui(data_bms->BMS->rt, queue_len - i, data_bms->BMS->points->coeffs[queue_lo + i]); } nmod_poly_set_coeff_ui(data_bms->BMS->rt, 0, 1); nmod_em_gcd_preinstantiated(data_bms->BMS, 0);//B->rt is pre-instantied if(data_bms->BMS->R1->length-1 == dim){ mp_limb_t inv = n_invmod(data_bms->BMS->R1->coeffs[data_bms->BMS->R1->length-1], (data_bms->BMS->R1->mod).n); nmod_poly_scalar_mul_nmod(data_bms->Z1, data_bms->BMS->V1, inv); nmod_poly_set_coeff_ui(data_bms->BMS->rt, queue_len+1, 1); for (long i = 0; i < queue_len; i++) { nmod_poly_set_coeff_ui(data_bms->BMS->rt, i + 1, data_bms->BMS->points->coeffs[queue_lo + i]); } nmod_poly_set_coeff_ui(data_bms->BMS->rt, 0, data_bms->BMS->R1->mod.n - 1); nmod_poly_one(data_bms->BMS->R0); //x^(2dim +1) nmod_poly_zero(data_bms->BMS->R1); nmod_poly_zero(data_bms->BMS->V0); nmod_poly_one(data_bms->BMS->V1); data_bms->BMS->npoints = 0; //(R_i, R_{i+1}, V_i, V_{i+1}) = EMGCD(R_0, R_1) nmod_em_gcd_preinstantiated(data_bms->BMS, 0); //Z2 = LC(R_{i+1})^{-1} x (V_{i+1}) inv = n_invmod(data_bms->BMS->R1->coeffs[data_bms->BMS->R1->length-1], (data_bms->BMS->R1->mod).n); nmod_poly_scalar_mul_nmod(data_bms->Z2, data_bms->BMS->V1, inv); fprintf(stderr, "Something should be checked\n"); return 1; } else{ fprintf(stderr, "There should be a bug here (invert_hankel)\n"); return 0; } } } return 1; } /* Z1 and Z2 must be arrays of length d + 1 Mirroring them will give an array of length d + 1 */ #if 0 static inline void solveHankel(nmod_poly_t param, nmod_poly_t Z1, nmod_poly_t Z2, nmod_poly_t rZ1, nmod_poly_t rZ2, nmod_poly_t A, nmod_poly_t B, szmat_t dimquot, szmat_t dim, CF_t *res, int ncoord, nmod_poly_t V, long disp){ V->length = dim; for(long i = 0; i < dim; i++){ V->coeffs[i] = res[ncoord-1+i*(dimquot)]; } #if DEBUGFGLM > 0 fprintf(stdout, "\n ncoord = %d\n", ncoord); fprintf(stdout, "V = "); nmod_poly_fprint_pretty(stdout, V, "x");fprintf(stdout, "\n\n"); #endif mirror_poly_inplace(V); mirror_poly_solve(rZ1, Z1, dim + 1); mirror_poly_solve(rZ2, Z2, dim + 1); nmod_poly_mullow(A, rZ1, V, dim); // mod t^dim nmod_poly_mullow(B, Z2, V, dim); // mod t^dim mirror_poly_inplace(B); mirror_poly_inplace(A); nmod_poly_mullow(rZ1, Z1, B, dim); nmod_poly_mullow(rZ2, rZ2, A, dim); nmod_poly_neg(rZ2, rZ2); nmod_poly_add(param, rZ1, rZ2); mp_limb_t inv = n_invmod(Z1->coeffs[0], (Z1->mod).n); nmod_poly_scalar_mul_nmod(param, param, inv); } #endif /* Z1 and Z2 must be arrays of length d + 1 Mirroring them will give an array of length d + 1 */ static inline void solve_hankel(fglm_bms_data_t *data_bms, szmat_t dimquot, szmat_t dim, szmat_t block_size, CF_t *res, int ncoord){ data_bms->V->length = dim; for(szmat_t i = 0; i < dim; i++){ data_bms->V->coeffs[i] = res[ncoord-1+i*(block_size)]; } #if DEBUGFGLM > 0 fprintf(stdout, "\n ncoord = %d\n", ncoord); fprintf(stdout, "V = "); nmod_poly_fprint_pretty(stdout, data_bms->V, "x"); fprintf(stdout, "\n"); #endif mirror_poly_inplace(data_bms->V); mirror_poly_solve(data_bms->rZ1, data_bms->Z1, dim + 1); mirror_poly_solve(data_bms->rZ2, data_bms->Z2, dim + 1); nmod_poly_mullow(data_bms->A, data_bms->rZ1, data_bms->V, dim); // mod t^dim nmod_poly_mullow(data_bms->B, data_bms->Z2, data_bms->V, dim); // mod t^dim mirror_poly_solve(data_bms->rZ1, data_bms->B, dim); for(szmat_t i = 0; i < dim ; i++){ data_bms->B->coeffs[i] = data_bms->rZ1->coeffs[i]; } data_bms->B->length = data_bms->rZ1->length; mirror_poly_solve(data_bms->rZ1, data_bms->A, dim); for(szmat_t i = 0; i < dim ; i++){ data_bms->A->coeffs[i] = data_bms->rZ1->coeffs[i]; } data_bms->A->length = data_bms->rZ1->length; nmod_poly_mullow(data_bms->rZ1, data_bms->Z1, data_bms->B, dim); nmod_poly_mullow(data_bms->rZ2, data_bms->rZ2, data_bms->A, dim); nmod_poly_neg(data_bms->rZ2, data_bms->rZ2); nmod_poly_add(data_bms->param, data_bms->rZ1, data_bms->rZ2); mp_limb_t inv = n_invmod(data_bms->Z1->coeffs[0], (data_bms->Z1->mod).n); nmod_poly_scalar_mul_nmod(data_bms->param, data_bms->param, inv); } /* Matrix vector product. Result is stored in res. vres will contain the product of the dense part. */ static inline void sparse_mat_fglm_mult_vec(CF_t *res, sp_matfglm_t *mat, CF_t *vec, CF_t *vres, const mod_t prime, //cf_l_t *vec_cache, //obsolete const uint32_t RED_32, const uint64_t RED_64, const uint32_t preinv, const uint32_t pi1, const uint32_t pi2, md_t *st){ szmat_t ncols = mat->ncols; szmat_t nrows = mat->nrows; szmat_t ntriv = ncols - nrows; for(szmat_t i = 0; i < ntriv; i++){ res[mat->triv_idx[i]] = vec[mat->triv_pos[i]]; } #ifdef HAVE_AVX2 _8mul_matrix_vector_product(vres, mat->dense_mat, vec, mat->dst, ncols, nrows, prime, RED_32, RED_64, preinv,st); #else non_avx_matrix_vector_product(vres, mat->dense_mat, vec, ncols, nrows, prime, RED_32, RED_64,st); #endif /* non_avx_matrix_vector_product(vres, mat->dense_mat, vec, */ /* ncols, nrows, prime, RED_32, RED_64,st); */ for(szmat_t i = 0; i < nrows; i++){ res[mat->dense_idx[i]] = vres[i]; } } /* Matrix vector product. Result is stored in res. vres will contain the product of the dense part. */ static inline void sparse_mat_fglm_colon_mult_vec(CF_t *res, sp_matfglmcol_t *mat, CF_t *vec, CF_t *vres, const mod_t prime, //cf_l_t *vec_cache, //obsolete const uint32_t RED_32, const uint64_t RED_64, const uint32_t preinv, const uint32_t pi1, const uint32_t pi2, md_t *st){ szmat_t ncols = mat->ncols; szmat_t nrows = mat->nrows; szmat_t nzero = mat->nzero; szmat_t ntriv = ncols - nrows - nzero; // ADD zero rows /* printf ("ncols: %d\nnrows: %d\nnzero: %d\nntriv: %d\n",ncols,nrows,nzero,ntriv); */ /* printf ("start\n"); */ for(szmat_t i = 0; i < ntriv; i++){ res[mat->triv_idx[i]] = vec[mat->triv_pos[i]]; } /* printf ("triv\n"); */ for(szmat_t i= 0; i < nzero; i++){ res[mat->zero_idx[i]] = 0; } /* printf ("zero\n"); */ /* printf("ncols %u\n", ncols); */ #ifdef HAVE_AVX2 /* matrix_vector_product(vres, mat->dense_mat, vec, ncols, nrows, prime, RED_32, RED_64); */ _8mul_matrix_vector_product(vres, mat->dense_mat, vec, mat->dst, ncols, nrows, prime, RED_32, RED_64, preinv,st); /* printf ("mul AVX\n"); */ #else non_avx_matrix_vector_product(vres, mat->dense_mat, vec, ncols, nrows, prime, RED_32, RED_64,st); /* printf ("mul non AVX\n"); */ #endif for(szmat_t i = 0; i < nrows; i++){ res[mat->dense_idx[i]] = vres[i]; } /* printf ("dense\n"); */ } /** FGLM mod prime. All needed intermediate data are allocated inside the function. Useful only for first call. **/ #if DEBUGFGLM static inline void print_vec(FILE *file, CF_t *vec, szmat_t len){ fprintf(file, "["); for(szmat_t i = 0; i < len-1; ++i){ fprintf(file, "%u, ", vec[i]); } fprintf(file, "%u]\n",vec[len-1]); } static inline void mynmod_berlekamp_massey_print(const nmod_berlekamp_massey_t B) { slong i; nmod_poly_fprint_pretty(stderr, B->V1, "x"); fprintf(stderr, ", "); for (i = 0; i < B->points->length; i++) { fprintf(stderr, " %lu", B->points->coeffs[i]); } } static inline void mynmod_berlekamp_massey_print_poly(FILE *file, const nmod_berlekamp_massey_t B) { slong i; fprintf(file, "%lu\n", B->V1->mod.n); for(i = 0; i < B->V1->length; ++i ){ fprintf(file, "%lu ", (B->V1->coeffs)[i]); } } #endif #if 0 static inline void generate_sequence(sp_matfglm_t *matrix, fglm_data_t * data, szmat_t block_size, long dimquot, mod_t prime){ uint32_t RED_32 = ((uint64_t)2<<31) % prime; #if DEBUGFGLM > 2 fprintf(stderr, "RED_32 = %u\n", RED_32); #endif uint32_t RED_64 = ((uint64_t)1<<63) % prime; RED_64 = (RED_64*2) % prime; #if DEBUGFGLM > 2 fprintf(stderr, "RED_64 = %u\n", RED_64); #endif uint32_t preinv = 2^(62) / prime; uint32_t pi1 = ((uint64_t)pow(2, 32)) / RED_64; uint32_t pi2 = (uint64_t)pow(2, 32) / RED_32; for(szmat_t i = 1; i < matrix->ncols; i++){ sparse_mat_fglm_mult_vec(data->vvec, matrix, data->vecinit, data->vecmult, prime, RED_32, RED_64, preinv, pi1, pi2, st); #if DEBUGFGLM > 1 print_vec(stderr, data->vvec, matrix->ncols); #endif CF_t *tmp = data->vecinit; data->vecinit = data->vvec; data->vvec = tmp; data->res[i*block_size] = data->vecinit[0]; for(szmat_t j = 1; j < block_size; j++){ data->res[j+i*block_size] = data->vecinit[j+1]; } #if DEBUGFGLM > 1 print_vec(stdout, data->res, 2*block_size * matrix->ncols); #endif #if DEBUGFGLM > 2 fprintf(stderr, "res = "); print_vec(stdout, data->res+i*matrix->ncols, matrix->ncols); #endif } for(szmat_t i = matrix->ncols; i < 2*matrix->ncols; i++){ sparse_mat_fglm_mult_vec(data->vvec, matrix, data->vecinit, data->vecmult, prime, RED_32, RED_64, preinv, pi1, pi2, st); #if DEBUGFGLM > 1 print_vec(stderr, data->vvec, matrix->ncols); #endif CF_t *tmp = data->vecinit; data->vecinit = data->vvec; data->vvec = tmp; data->res[i*block_size] = data->vecinit[0]; #if DEBUGFGLM > 1 print_vec(stdout, data->res, 2*block_size * matrix->ncols); #endif #if DEBUGFGLM > 2 fprintf(stderr, "res = "); print_vec(stdout, data->res+i*matrix->ncols, matrix->ncols); #endif } /* now res contains our generating sequence */ for(ulong i = 0; i < 2 * dimquot; i++){ data->pts[i] = data->res[i*block_size]; } } #endif static void generate_matrix_sequence(sp_matfglm_t *matxn, fglm_data_t * data, szmat_t block_size, long dimquot, nvars_t* squvars, nvars_t* linvars, long nvars, mod_t prime, md_t *st){ uint32_t RED_32 = ((uint64_t)2<<31) % prime; uint32_t RED_64 = ((uint64_t)1<<63) % prime; RED_64 = (RED_64*2) % prime; const uint32_t preinv = 2^(62) / prime; const szmat_t ncols = matxn->ncols; const szmat_t nrows = matxn->nrows; const int BL = 16; /* allocates random matrix */ CF_t *Rmat ALIGNED32; if(posix_memalign((void **)&Rmat, 32, BL*ncols*sizeof(CF_t))){ fprintf(stderr, "posix_memalign failed\n"); exit(1); } memset(Rmat, 0, (ncols)*sizeof(CF_t)); for(szmat_t i = 0; i < BL*ncols; i++){ Rmat[i] = 0; } for(szmat_t i = 0; i < matxn->ncols; i++){ Rmat[i] = (CF_t)rand() % prime; Rmat[i] += (CF_t)rand() % prime; } /* allocates result matrix (matxn * Rmat) */ CF_t *res ALIGNED32; if(posix_memalign((void **)&res, 32, BL*ncols*sizeof(CF_t))){ fprintf(stderr, "posix_memalign failed\n"); exit(1); } memset(res, 0, BL*ncols*sizeof(CF_t)); /* allocates temporary matrix */ CF_t *tres ALIGNED32; if(posix_memalign((void **)&tres, 32, nrows*ncols*sizeof(CF_t))){ fprintf(stderr, "posix_memalign failed\n"); exit(1); } memset(tres, 0, nrows*ncols*sizeof(CF_t)); szmat_t nb = 2 * matxn->ncols / BL; for(szmat_t i = 0; i < nb; i++){ sparse_matfglm_mul(res, matxn, Rmat, tres, BL, prime, preinv, RED_32, RED_64); } free(Rmat); free(res); free(tres); } static void generate_sequence_verif(sp_matfglm_t *matrix, fglm_data_t * data, szmat_t block_size, szmat_t dimquot, nvars_t* squvars, nvars_t* linvars, nvars_t nvars, mod_t prime, md_t *st){ uint32_t RED_32 = ((uint64_t)2<<31) % prime; uint32_t RED_64 = ((uint64_t)1<<63) % prime; RED_64 = (RED_64*2) % prime; uint32_t preinv = 2^(62) / prime; uint32_t pi1 = ((uint64_t)pow(2, 32)) / RED_64; uint32_t pi2 = (uint64_t)pow(2, 32) / RED_32; int dec= 0; for(szmat_t j = 1; j < block_size; j++){ while (nvars-1-j-dec > 0 && linvars[nvars-1-j-dec] != 0) { dec++; } data->res[j+matrix->ncols*block_size] = data->vecinit[squvars[nvars-1-j-dec]]; } for(szmat_t i = 1; i < matrix->ncols; i++){ sparse_mat_fglm_mult_vec(data->vvec, matrix, data->vecinit, data->vecmult, prime, RED_32, RED_64, preinv, pi1, pi2, st); #if DEBUGFGLM > 1 print_vec(stderr, data->vvec, matrix->ncols); #endif CF_t *tmp = data->vecinit; data->vecinit = data->vvec; data->vvec = tmp; data->res[i*block_size] = data->vecinit[0]; dec = 0; for(szmat_t j = 1; j < block_size; j++){ data->res[j+i*block_size] = data->vecinit[j+1]; while (linvars[nvars-1-j-dec] != 0) { dec++; } data->res[j+(i+matrix->ncols)*block_size] = data->vecinit[squvars[nvars-1-j-dec]]; } #if DEBUGFGLM > 1 print_vec(stdout, data->res, 2*block_size * matrix->ncols); #endif #if DEBUGFGLM > 2 fprintf(stderr, "res = "); print_vec(stdout, data->res+i*matrix->ncols, matrix->ncols); #endif } for(szmat_t i = matrix->ncols; i < 2*matrix->ncols; i++){ sparse_mat_fglm_mult_vec(data->vvec, matrix, data->vecinit, data->vecmult, prime, RED_32, RED_64, preinv, pi1, pi2, st); #if DEBUGFGLM > 1 print_vec(stderr, data->vvec, matrix->ncols); #endif CF_t *tmp = data->vecinit; data->vecinit = data->vvec; data->vvec = tmp; data->res[i*block_size] = data->vecinit[0]; #if DEBUGFGLM > 1 print_vec(stdout, data->res, 2*block_size * matrix->ncols); #endif #if DEBUGFGLM > 2 fprintf(stderr, "res = "); print_vec(stdout, data->res+i*matrix->ncols, matrix->ncols); #endif } /* now res contains our generating sequence */ for(ulong i = 0; i < 2 * dimquot; i++){ data->pts[i] = data->res[i*block_size]; } } static inline void compute_elim_poly(fglm_data_t *data, fglm_bms_data_t *data_bms, long dimquot){ nmod_berlekamp_massey_add_points(data_bms->BMS, data->pts, 2*dimquot); nmod_berlekamp_massey_reduce(data_bms->BMS); nmod_poly_make_monic(data_bms->BMS->V1, data_bms->BMS->V1); } static inline long make_square_free_elim_poly(param_t *param, fglm_bms_data_t *data_bms, long dimquot, int info_level){ long dim = data_bms->BMS->V1->length - 1; int boo = nmod_poly_is_squarefree(data_bms->BMS->V1); if(boo && dim == dimquot){ nmod_poly_set(param->elim, data_bms->BMS->V1); nmod_poly_one(param->denom); } else{ if(boo==0){ if(info_level){ fprintf(stderr, "Mininimal polynomial is not square-free\n"); } } nmod_poly_factor_squarefree(data_bms->sqf, data_bms->BMS->V1); nmod_poly_one(param->elim); nmod_poly_one(param->denom); for(ulong i = 0; i < data_bms->sqf->num; i++){ nmod_poly_mul(param->elim, param->elim, data_bms->sqf->p+i); } if(info_level){ fprintf(stderr, "Degree of the square-free part: %ld\n", param->elim->length-1); fprintf(stderr, "[%ld, %ld, %ld]\n", dimquot, dim, param->elim->length - 1); } } data_bms->sqf->num=0; return param->elim->length - 1; } static inline long make_square_free_elim_poly_colon(param_t *param, fglm_bms_data_t *data_bms, long dimquot, int info_level){ long dim = data_bms->BMS->V1->length - 1; int boo = nmod_poly_is_squarefree(data_bms->BMS->V1); if(boo){ nmod_poly_set(param->elim, data_bms->BMS->V1); } else{ if(info_level){ fprintf(stderr, "Mininimal polynomial is not square-free\n"); } nmod_poly_factor_squarefree(data_bms->sqf, data_bms->BMS->V1); nmod_poly_one(param->elim); for(ulong i = 0; i < data_bms->sqf->num; i++){ nmod_poly_mul(param->elim, param->elim, data_bms->sqf->p+i); } if(info_level){ fprintf(stderr, "Degree of the square-free part: %ld\n", param->elim->length-1); fprintf(stderr, "[%ld, %ld, %ld]\n", dimquot, dim, param->elim->length - 1); } } data_bms->sqf->num=0; return param->elim->length - 1; } static inline void compute_minpoly(param_t *param, fglm_data_t *data, fglm_bms_data_t *data_bms, long dimquot, nvars_t *linvars, uint32_t *lineqs, long nvars, long *dim, int info_level){ compute_elim_poly(data, data_bms, dimquot); if(data_bms->BMS->V1->length == 1){ nmod_poly_fit_length(data_bms->BMS->V1, 2); data_bms->BMS->V1->length = 2; data_bms->BMS->V1->coeffs[0] = 0; data_bms->BMS->V1->coeffs[1] = 1; } *dim = make_square_free_elim_poly(param, data_bms, dimquot, info_level); } static void set_param_linear_vars(param_t *param, szmat_t nlins, nvars_t *linvars, uint32_t *lineqs, nvars_t nvars){ int cnt = 1; const uint32_t fc = param->charac; int nr = 0; if(nlins==nvars){ nr = nvars - 1; param->elim->length = 2; param->elim->coeffs[1] = 1; param->elim->coeffs[0] = lineqs[nlins*(nvars + 1) - 1]; } else{ nr = nlins; } for(nvars_t nc = nvars - 2; nc >= 0; nc--){ int ind = nc; if(linvars[nc] != 0){ nmod_poly_fit_length(param->coords[ind], param->elim->length); param->coords[ind]->coeffs[param->coords[ind]->length-1] = 0; param->coords[ind]->length = param->elim->length; for(szmat_t i = 0; i < param->coords[ind]->length; i++){ param->coords[ind]->coeffs[i] = 0; } for(nvars_t k = 1; k < nvars - 1 ; k++){ uint64_t c = lineqs[k+(nvars+1)*(nr-(cnt-1)-1)]; if(c){ /* one multiplies param->coords[k] by fc -c */ /* and adds this to param->coords[ind] */ uint32_t cc = (fc - c); for(int i = 0; i < param->coords[k]->length; i++){ uint64_t tmp = cc * (uint64_t)param->coords[k]->coeffs[i]; tmp = tmp % fc; tmp += param->coords[ind]->coeffs[i]; tmp = tmp % fc; param->coords[ind]->coeffs[i] = tmp; } } } uint64_t c1 = lineqs[nvars - 1 +(nvars+1)*(nr-(cnt-1)-1)]; param->coords[ind]->coeffs[1] = ((uint64_t)(param->coords[ind]->coeffs[1] + c1)) % fc; uint64_t c0 = lineqs[nvars +(nvars+1)*(nr-(cnt-1)-1)]; param->coords[ind]->coeffs[0] = ((uint64_t)(param->coords[ind]->coeffs[0] + c0)) % fc; for(deg_t k = param->coords[ind]->length - 1; k >= 0; k--){ if(param->coords[ind]->coeffs[k] == 0){ param->coords[ind]->length--; } else{ break; } } nmod_poly_rem(param->coords[ind], param->coords[ind], param->elim); for(deg_t k = param->coords[ind]->length - 1; k >= 0; k--){ if(param->coords[ind]->coeffs[k] == 0){ param->coords[ind]->length--; } else{ break; } } cnt++; } } #if DEBUGFGLM >0 display_fglm_param(stderr, param); #endif } static int compute_parametrizations(param_t *param, fglm_data_t *data, fglm_bms_data_t *data_bms, szmat_t dim, szmat_t dimquot, szmat_t block_size, szmat_t nlins, nvars_t *linvars, uint32_t *lineqs, szmat_t nvars){ nmod_poly_one(param->denom); int b = 1; if(nlins != nvars){ b = invert_hankel_matrix(data_bms, dim); #if DEBUGFGLM > 0 fprintf(stdout, "Z1 = "); nmod_poly_fprint_pretty(stdout, data_bms->Z1, "x");fprintf(stdout, "\n"); fprintf(stdout, "Z2 = "); nmod_poly_fprint_pretty(stdout, data_bms->Z2, "x");fprintf(stdout, "\n"); #endif } if(b){ szmat_t dec = 0; for(nvars_t nc = 0; nc < nvars - 1 ; nc++){ if(linvars[nvars - 2- nc] == 0){ solve_hankel(data_bms, dimquot, dim, block_size, data->res, nc + 2 - dec); nmod_poly_neg(data_bms->param, data_bms->param); nmod_poly_reverse(param->coords[nvars-2-nc], data_bms->param, dim); nmod_poly_rem(param->coords[nvars-2-nc], param->coords[nvars-2-nc], param->elim); #if DEBUGFGLM > 0 nmod_poly_fprint_pretty(stdout, param->coords[nvars-2-nc], "X"); fprintf(stdout, "\n"); #endif } else{ if(param->coords[nvars-2-nc]->alloc < param->elim->alloc - 1){ nmod_poly_fit_length(param->coords[nvars-2-nc], param->elim->length-1 ); } param->coords[nvars-2-nc]->length = param->elim->length-1 ; for(deg_t i = 0; i < param->elim->length-1 ; i++){ param->coords[nvars-2-nc]->coeffs[i] = 0; } dec++; } } set_param_linear_vars(param, nlins, linvars, lineqs, nvars); #if DEBUGFGLM > 0 fprintf(stderr, "PARAM = "); display_fglm_param_maple(stderr, param); fprintf(stderr, "\n"); #endif return 1; } else{ return 0; } } static inline int invert_table_polynomial (param_t *param, fglm_data_t *data, fglm_bms_data_t *data_bms, ulong dimquot, szmat_t block_size, mod_t prime, int ncoord, uint64_t lambda) { szmat_t length= data_bms->BMS->V1->length-1; nmod_poly_zero(data_bms->BMS->R0); nmod_poly_zero(data_bms->Z1); nmod_poly_zero(data_bms->Z2); nmod_poly_fit_length(data_bms->BMS->R0, length); nmod_poly_fit_length(data_bms->BMS->R0, length); for (long i = 0; i < length; i++){ if (lambda == 0) { nmod_poly_set_coeff_ui (data_bms->BMS->R0,i, data->res[(length-i-1)*block_size+ncoord]); } else { uint64_t coeff= (lambda*data->res[(length-i-1)*block_size]) % prime; coeff= (data->res[(length-i-1)*block_size+ncoord] + coeff) % prime; nmod_poly_set_coeff_ui (data_bms->BMS->R0,i, coeff); } } nmod_poly_mul (data_bms->Z1,data_bms->BMS->R0,data_bms->BMS->V1); nmod_poly_shift_right (data_bms->Z1,data_bms->Z1,length); nmod_poly_xgcd (data_bms->BMS->R0,data_bms->BMS->R1,data_bms->Z2,param->elim, data_bms->Z1); return (nmod_poly_degree (data_bms->BMS->R0) == 0); } static inline void divide_table_polynomials (param_t *param, fglm_data_t *data, fglm_bms_data_t *data_bms, ulong dimquot, szmat_t block_size, mod_t prime, int ncoord, uint64_t lambda) { szmat_t length= data_bms->BMS->V1->length-1; nmod_poly_zero (data_bms->BMS->R0); nmod_poly_fit_length(data_bms->BMS->R0, length); for (long i = 0; i < length; i++){ if (lambda == 0) { nmod_poly_set_coeff_ui (data_bms->BMS->R0,i, data->res[(length-i-1)*block_size+ncoord]); } else { uint64_t coeff= (lambda*data->res[(length-i-1)*block_size+ncoord]) % prime; coeff= (data->res[(dimquot+length-i-1)*block_size+ncoord] + coeff) % prime; nmod_poly_set_coeff_ui (data_bms->BMS->R0,i, coeff); } } nmod_poly_mul (data_bms->BMS->R1,data_bms->BMS->R0,data_bms->BMS->V1); nmod_poly_shift_right (data_bms->BMS->R1,data_bms->BMS->R1,length); nmod_poly_mul (data_bms->BMS->R1,data_bms->BMS->R1,data_bms->Z2); nmod_poly_rem (data_bms->BMS->R1,data_bms->BMS->R1,param->elim); } static inline void divide_table_polynomials_colon (param_t *param, fglm_data_t *data, fglm_bms_data_t *data_bms, ulong dimquot, szmat_t block_size, mod_t prime, int ncoord, const long nvars, uint64_t lambda) { szmat_t length= data_bms->BMS->V1->length-1; nmod_poly_zero (data_bms->BMS->R0); nmod_poly_fit_length(data_bms->BMS->R0, length); for (long i = 0; i < length; i++){ if (lambda == 0) { nmod_poly_set_coeff_ui (data_bms->BMS->R0,i, data->res[(length-i-1)*block_size+ncoord]); } else { uint64_t coeff= (lambda*data->res[(length-i-1)*block_size+ncoord]) % prime; coeff= (data->res[(length-i-1)*block_size+(nvars-1)+ncoord] + coeff) % prime; nmod_poly_set_coeff_ui (data_bms->BMS->R0,i, coeff); } } nmod_poly_mul (data_bms->BMS->R1,data_bms->BMS->R0,data_bms->BMS->V1); nmod_poly_shift_right (data_bms->BMS->R1,data_bms->BMS->R1,length); nmod_poly_mul (data_bms->BMS->R1,data_bms->BMS->R1,data_bms->Z2); nmod_poly_rem (data_bms->BMS->R1,data_bms->BMS->R1,param->elim); } static int compute_parametrizations_non_shape_position_case(param_t *param, fglm_data_t *data, fglm_bms_data_t *data_bms, ulong dimquot, szmat_t block_size, nvars_t nlins, nvars_t *linvars, uint32_t *lineqs, nvars_t *squvars, long nvars, mod_t prime, int verif){ int nr_fail_param=-1; if (invert_table_polynomial (param, data, data_bms, dimquot, block_size, prime, 0, 0)) { #if DEBUGFGLM > 0 fprintf (stdout,"C1="); nmod_poly_fprint_pretty (stdout, data_bms->Z1, "x"); fprintf (stdout,"\n"); fprintf(stdout, "invC1="); nmod_poly_fprint_pretty (stdout, data_bms->Z2, "x"); fprintf (stdout,"\n"); #endif long dec = 0; for(long nc = 0; nc < nvars - 1 ; nc++){ if(linvars[nvars - 2 - nc] == 0){ divide_table_polynomials(param,data,data_bms, dimquot, block_size, prime, nc + 1-dec,0); if(data_bms->BMS->R1->length>0){ nmod_poly_neg(param->coords[nvars-2-nc], data_bms->BMS->R1); } else{ nmod_poly_fit_length(param->coords[nvars-2-nc], param->elim->length-1 ); param->coords[nvars-2-nc]->length = data_bms->BMS->R1->length ; param->coords[nvars-2-nc]->coeffs[0] = 0; param->coords[nvars-2-nc]->coeffs[1] = 0; } #if DEBUGFGLM > 0 nmod_poly_fprint_pretty(stdout, param->coords[nvars-2-nc], "X"); fprintf(stdout, "\n"); #endif } else{ dec++; if(param->coords[nvars-2-nc]->alloc < param->elim->alloc - 1){ nmod_poly_fit_length(param->coords[nvars-2-nc], param->elim->length-1 ); } param->coords[nvars-2-nc]->length = param->elim->length-1 ; for(long i = 0; i < param->elim->length-1 ; i++){ param->coords[nvars-2-nc]->coeffs[i] = 0; } } } /* parametrizations verification */ if (verif) { dec = 0; for(long nc = 0; nc < nvars - 1 ; nc++){ if(linvars[nvars - 2 - nc] == 0 && squvars[nvars - 2 - nc] != 0){ uint64_t lambda= 1 + ((uint64_t) rand() % (prime-1)); /* needed for verification */ invert_table_polynomial (param, data, data_bms, dimquot, block_size, prime, nc+1-dec, lambda); #if DEBUGFGLM > 1 fprintf (stdout,"C2="); nmod_poly_fprint_pretty (stdout, data_bms->Z1, "x"); fprintf (stdout,"\n"); fprintf(stdout, "invC2="); nmod_poly_fprint_pretty (stdout, data_bms->Z2, "x"); fprintf (stdout,"\n"); #endif divide_table_polynomials(param,data,data_bms, dimquot, block_size, prime, nc+1-dec,lambda); nmod_poly_neg(data_bms->BMS->R1, data_bms->BMS->R1); #if DEBUGFGLM > 1 nmod_poly_fprint_pretty(stdout, data_bms->BMS->R1, "X"); fprintf(stdout, "\n"); #endif if (! nmod_poly_equal (param->coords[nvars-2-nc],data_bms->BMS->R1)) { if (nr_fail_param == -1) { nr_fail_param= nvars-2-nc; } } } else{ /* might happen that the ideal is non radical and still some squared variables are not in the quotient. In that case, a random linear form has been introduced. */ if(linvars[nvars - 2 - nc] != 0){ if(param->coords[nvars-2-nc]->alloc < param->elim->alloc ){ nmod_poly_fit_length(param->coords[nvars-2-nc], param->elim->alloc ); } param->coords[nvars-2-nc]->length = param->elim->length ; for(long i = 0; i < param->elim->length ; i++){ param->coords[nvars-2-nc]->coeffs[i] = 0; } } } if(linvars[nvars - 2 - nc] != 0){ dec++; } } } set_param_linear_vars(param, nlins, linvars, lineqs, nvars); #if DEBUGFGLM>0 display_fglm_param_maple(stderr, param); #endif return nvars-1-nr_fail_param; } else { return 0; } } static int compute_parametrizations_colon(param_t *param, fglm_data_t *data, fglm_bms_data_t *data_bms, ulong dimquot, szmat_t block_size, nvars_t nlins, nvars_t *linvars, uint32_t *lineqs, nvars_t *squvars, long nvars, mod_t prime, int verif){ int nr_fail_param=-1; if (invert_table_polynomial (param, data, data_bms, dimquot, block_size, prime, 0, 0)) { #if DEBUGFGLM > 0 fprintf (stdout,"C1="); nmod_poly_fprint_pretty (stdout, data_bms->Z1, "x"); fprintf (stdout,"\n"); fprintf(stdout, "invC1="); nmod_poly_fprint_pretty (stdout, data_bms->Z2, "x"); fprintf (stdout,"\n"); #endif long dec = 0; for(long nc = 0; nc < nvars - 1 ; nc++){ if(linvars[nvars - 2 - nc] == 0){ divide_table_polynomials_colon(param,data,data_bms, dimquot, block_size, prime, nc + 1-dec,nvars,0); nmod_poly_neg(param->coords[nvars-2-nc], data_bms->BMS->R1); #if DEBUGFGLM > 0 nmod_poly_fprint_pretty(stdout, param->coords[nvars-2-nc], "X"); fprintf(stdout, "\n"); #endif } else{ dec++; } } /* parametrizations verification */ if (verif) { dec = 0; for(long nc = 0; nc < nvars - 1 ; nc++){ if(linvars[nvars - 2 - nc] == 0 && squvars[nvars - 2 - nc] != 0){ uint64_t lambda= 1 + ((uint64_t) rand() % (prime-1)); /* needed for verification */ invert_table_polynomial (param, data, data_bms, dimquot, block_size, prime, nc+1-dec, lambda); #if DEBUGFGLM > 1 fprintf (stdout,"C2="); nmod_poly_fprint_pretty (stdout, data_bms->Z1, "x"); fprintf (stdout,"\n"); fprintf(stdout, "invC2="); nmod_poly_fprint_pretty (stdout, data_bms->Z2, "x"); fprintf (stdout,"\n"); #endif divide_table_polynomials_colon(param,data,data_bms, dimquot, block_size, prime, nc+1-dec,nvars,lambda); nmod_poly_neg(data_bms->BMS->R1, data_bms->BMS->R1); #if DEBUGFGLM > 1 nmod_poly_fprint_pretty(stdout, data_bms->BMS->R1, "X"); fprintf(stdout, "\n"); #endif if (! nmod_poly_equal (param->coords[nvars-2-nc],data_bms->BMS->R1)) { if (nr_fail_param == -1) { nr_fail_param= nvars-2-nc; } } } else{ if(linvars[nvars -2 - nc] != 0){ if(param->coords[nvars-2-nc]->alloc < param->elim->alloc - 1){ nmod_poly_fit_length(param->coords[nvars-2-nc], param->elim->alloc ); } param->coords[nvars-2-nc]->length = param->elim->length-1 ; for(long i = 0; i < param->elim->length-1 ; i++){ param->coords[nvars-2-nc]->coeffs[i] = 0; } } } if(linvars[nvars - 2 - nc] != 0){ dec++; } } } set_param_linear_vars(param, nlins, linvars, lineqs, nvars); #if DEBUGFGLM>0 display_fglm_param_maple(stderr, param); #endif return nvars-1-nr_fail_param; } else { return 0; } } static inline long initialize_fglm_data(sp_matfglm_t *matrix, fglm_data_t *data, const mod_t prime, const szmat_t sz, const szmat_t block_size){ szmat_t nb = 0; for(szmat_t i = 0; i < sz; i++){ if(matrix->dense_mat[i]==0) nb++; } srand(time(0)); for(szmat_t i = 0; i < matrix->ncols; i++){ data->vecinit[i] = (CF_t)rand() % prime; } data->res[0] = data->vecinit[0]; for(szmat_t i = 1; i < block_size; i++){ data->res[i] = data->vecinit[i+1]; } return nb; } static inline long initialize_fglm_colon_data(sp_matfglmcol_t *matrix, fglm_data_t *data, const mod_t prime, const szmat_t sz, const szmat_t block_size){ szmat_t nb = 0; for(szmat_t i = 0; i < sz; i++){ if(matrix->dense_mat[i]==0) nb++; } srand(time(0)); for(szmat_t i = 0; i < matrix->ncols; i++){ data->vecinit[i] = (CF_t)rand() % prime; data->vecinit[i] += (CF_t)rand() % prime; /* data->vecinit[i] = (CF_t)(i+1) % prime; */ } data->res[0] = data->vecinit[0]; for(szmat_t i = 1; i < block_size; i++){ data->res[i] = data->vecinit[i+1]; } return nb; } param_t *nmod_fglm_compute(sp_matfglm_t *matrix, const mod_t prime, const nvars_t nvars, const szmat_t nlins, nvars_t *linvars, uint32_t *lineqs, nvars_t *squvars, const int info_level, md_t *st){ #if DEBUGFGLM > 0 fprintf(stderr, "prime = %u\n", prime); #endif #if DEBUGFGLM >= 1 FILE *fmat = fopen("/tmp/matrix.fglm", "w"); display_fglm_matrix(fmat, matrix); fclose(fmat); #endif /* 1147878294 */ if(prime>=1518500213){ fprintf(stderr, "Prime %u is too large.\n", prime); fprintf(stderr, "One needs to use update linear algebra fglm functions\n"); return NULL; } szmat_t block_size = nvars-nlins; fglm_data_t *data = allocate_fglm_data(matrix->nrows, matrix->ncols, nvars); param_t *param = allocate_fglm_param(prime, nvars); long sz = matrix->ncols * matrix->nrows; long nb = initialize_fglm_data(matrix, data, prime, sz, block_size); if(info_level){ fprintf(stderr, "[%u, %u], Non trivial / Trivial = %.2f%%\n", matrix->ncols, matrix->nrows, 100*((double)matrix->nrows / (double)matrix->ncols)); fprintf(stderr, "Density of non-trivial part %.2f%%\n", 100-100*(float)nb/(float)sz); } szmat_t dimquot = (matrix->ncols); #if DEBUGFGLM > 1 print_vec(stderr, data->vecinit, matrix->ncols); print_vec(stderr, data->res, 2 * block_size * matrix->ncols); fprintf(stderr, "\n"); #endif double st1 = realtime(); #ifdef BLOCKWIED fprintf(stderr, "Starts computation of matrix sequence\n"); double st0 = omp_get_wtime(); generate_matrix_sequence(matrix, data, block_size, dimquot, squvars, linvars, nvars, prime, st); double et0 = omp_get_wtime() - st0; fprintf(stderr, "Matrix sequence computed\n"); fprintf(stderr, "Elapsed time : %.2f\n", et0); fprintf(stderr, "Implementation to be completed\n"); // pick some nbrows, nbcols, length // (matrix sequence has "2*glen" matrices of size "gdim x gdim" slong gdim = 16; slong glen = 4096; nmod_mat_poly_t matp; nmod_mat_poly_init2(matp, 2*gdim, gdim, prime, 2*glen); // top gdim x gdim submatrix matrices is formed from the matrix sequence // for the moment, let's take random coefficients flint_rand_t state; flint_randinit(state); srand(time(0)); flint_randseed(state, rand(), rand()); for (slong k = 0; k < 2*glen; k++) { mp_ptr vec = (matp->coeffs + k)->entries; for (slong i = 0; i < gdim*gdim; i++) vec[i] = n_randint(state, matp->mod.n); } // bottom gdim x gdim submatrix is -identity for (slong i = 0; i < gdim; i++) nmod_mat_entry(matp->coeffs + 0, gdim+i, i) = prime-1; // convert to poly_mat pmat, and forget matp double st_recon = omp_get_wtime(); nmod_poly_mat_t pmat; nmod_poly_mat_set_from_mat_poly(pmat, matp); nmod_mat_poly_clear(matp); // fraction reconstruction nmod_poly_mat_t appbas; nmod_poly_mat_init(appbas, 2*gdim, 2*gdim, prime); nmod_poly_mat_pmbasis(appbas, NULL, pmat, 2*glen); // extract generator and forget appbas nmod_poly_mat_t gen; nmod_poly_mat_init(gen, gdim, gdim, prime); for (slong i = 0; i < gdim; i++) for (slong j = 0; j < gdim; j++) nmod_poly_swap(gen->rows[i] + j, appbas->rows[i] + j); nmod_poly_mat_clear(appbas); double tt_recon = omp_get_wtime() - st_recon; fprintf(stderr, "Matrix generator computed\n"); fprintf(stderr, "Elapsed time : %.2f\n", tt_recon); fprintf(stderr, "Implementation to be completed\n"); exit(1); #else generate_sequence_verif(matrix, data, block_size, dimquot, squvars, linvars, nvars, prime, st); #endif if(info_level > 1){ double nops = 2 * (matrix->nrows/ 1000.0) * (matrix->ncols / 1000.0) * (matrix->ncols / 1000.0); double rt1 = realtime()-st1; fprintf(stderr, "Time spent to generate sequence (elapsed): %.2f sec (%.2f Gops/sec)\n", rt1, nops / rt1); } st1 = realtime(); /* Berlekamp-Massey data */ fglm_bms_data_t *data_bms = allocate_fglm_bms_data(dimquot, prime); long dim = 0; compute_minpoly(param, data, data_bms, dimquot, linvars, lineqs, nvars, &dim, info_level); if(info_level){ fprintf(stderr, "Time spent to compute eliminating polynomial (elapsed: %.2f sec\n", realtime()-st1); } if (dimquot == dim) { if(info_level){ fprintf(stderr, "Elimination polynomial is squarefree.\n"); } st1 = realtime(); if(compute_parametrizations(param, data, data_bms, dim, dimquot, block_size, nlins, linvars, lineqs, nvars) == 0){ fprintf(stderr, "Matrix is not invertible (there should be a bug)\n"); free_fglm_bms_data(data_bms); free_fglm_data(data); return NULL; } } else { fprintf(stderr, "Elimination polynomial is not squarefree.\n"); int right_param= compute_parametrizations_non_shape_position_case(param, data, data_bms, dimquot, block_size, nlins, linvars, lineqs, squvars, nvars, prime, 1); /* verif */ if (right_param == 0) { fprintf(stderr, "Matrix is not invertible (there should be a bug)\n"); free_fglm_bms_data(data_bms); free_fglm_data(data); return NULL; } else if (right_param == 1) { fprintf(stderr, "Radical ideal might have no correct parametrization\n"); } else if (right_param < nvars) { fprintf(stderr, "Only the first %d parametrizations of ",right_param-1); } else { fprintf(stderr, "All the parametrizations of "); fprintf(stderr, "the radical ideal are correct\n"); } } if(info_level){ fprintf(stderr, "Time spent to compute parametrizations (elapsed): %.2f sec\n", realtime()-st1); fprintf(stderr, "Parametrizations done.\n"); } free_fglm_bms_data(data_bms); free_fglm_data(data); return param; } param_t *nmod_fglm_compute_trace_data(sp_matfglm_t *matrix, mod_t prime, szmat_t nvars, szmat_t block_size, //taille de bloc dans data->res szmat_t nlins, nvars_t *linvars, uint32_t *lineqs, nvars_t *squvars, int info_level, fglm_data_t **bdata, fglm_bms_data_t **bdata_bms, int *success, md_t *st){ #if DEBUGFGLM > 0 fprintf(stderr, "prime = %u\n", prime); #endif #if DEBUGFGLM >= 1 FILE *fmat = fopen("/tmp/matrix.fglm", "w"); display_fglm_matrix(fmat, matrix); fclose(fmat); #endif /* 1147878294 */ if(prime>=1518500213){ fprintf(stderr, "Prime %u is too large.\n", prime); fprintf(stderr, "One needs to use updated linear algebra fglm functions\n"); return NULL; } /* to store the terms we need */ *bdata = allocate_fglm_data(matrix->nrows, matrix->ncols, nvars); param_t *param = allocate_fglm_param(prime, nvars); szmat_t sz = matrix->ncols * matrix->nrows; szmat_t nb = initialize_fglm_data(matrix, *bdata, prime, sz, block_size); if(info_level){ fprintf(stderr, "[%u, %u], Non trivial / Trivial = %.2f%%\n", matrix->ncols, matrix->nrows, 100*((double)matrix->nrows / (double)matrix->ncols)); fprintf(stderr, "Density of non-trivial part %.2f%%\n", 100-100*(float)nb/(float)sz); } szmat_t dimquot = (matrix->ncols); double st_fglm = realtime(); #if BLOCKWIED > 0 fprintf(stderr, "Starts computation of matrix sequence\n"); double st0 = omp_get_wtime(); generate_matrix_sequence(matrix, *bdata, block_size, dimquot, squvars, linvars, nvars, prime, st); double et0 = omp_get_wtime() - st0; fprintf(stderr, "Matrix sequence computed\n"); fprintf(stderr, "Elapsed time : %.2f\n", et0); fprintf(stderr, "Implementation to be completed\n"); exit(1); #else generate_sequence_verif(matrix, *bdata, block_size, dimquot, squvars, linvars, nvars, prime, st); #endif if(info_level){ double nops = 2 * (matrix->nrows/ 1000.0) * (matrix->ncols / 1000.0) * (matrix->ncols / 1000.0); double rt_fglm = realtime()-st_fglm; fprintf(stderr, "Time spent to generate sequence (elapsed): %.2f sec (%.2f Gops/sec)\n", rt_fglm, nops / rt_fglm); } st_fglm = realtime(); /* Berlekamp-Massey data */ *bdata_bms = allocate_fglm_bms_data(dimquot, prime); long dim = 0; compute_minpoly(param, *bdata, *bdata_bms, dimquot, linvars, lineqs, nvars, &dim, info_level); if(info_level){ fprintf(stderr, "Time spent to compute eliminating polynomial (elapsed): %.2f sec\n", realtime()-st_fglm); } if (dimquot == dim) { if(info_level){ fprintf(stderr, "Elimination polynomial has degree %d.\n", dimquot); } if(compute_parametrizations(param, *bdata, *bdata_bms, dim, dimquot, block_size, nlins, linvars, lineqs, nvars) == 0){ fprintf(stderr, "Matrix is not invertible (there should be a bug)\n"); return NULL; } } else { /* computes the param of the radical */ if(info_level){ fprintf(stderr, "Elimination polynomial is not squarefree.\n"); } int right_param= compute_parametrizations_non_shape_position_case(param, *bdata, *bdata_bms, dimquot, block_size, nlins, linvars, lineqs, squvars, nvars, prime, 1); /* verif */ if (right_param == 0) { if(info_level){ fprintf(stderr, "Matrix is not invertible (there should be a bug)\n"); } *success = 0; return NULL; } else if (right_param == 1) { if(info_level){ fprintf(stderr, "Ideal not in generic position, parametrizations are not correct\n"); } *success = 0; } else if (right_param < nvars) { if(info_level){ fprintf(stderr, "Only the first %d parametrizations of ",right_param-1); fprintf(stderr, "the radical ideal are correct\n"); } *success = 0; } } return param; } /* Fonction qui applique sparse FGLM apres le premier round dans un process multi-mod. Renvoie 0 si le calcul est correct ; si non on renvoie 1 */ int nmod_fglm_compute_apply_trace_data(sp_matfglm_t *matrix, const mod_t prime, param_t *param, const long nvars, const long bsz, const long nlins, nvars_t *linvars, uint32_t *lineqs, nvars_t *squvars, fglm_data_t *data_fglm, fglm_bms_data_t *data_bms, const long deg_init, const int info_level, md_t *st){ #if DEBUGFGLM > 0 fprintf(stderr, "prime = %u\n", prime); #endif #if DEBUGFGLM >= 1 FILE *fmat = fopen("/tmp/matrix.fglm", "w"); display_fglm_matrix(fmat, matrix); fclose(fmat); #endif if(prime>=1518500213){ fprintf(stderr, "Prime %u is too large.\n", prime); fprintf(stderr, "One needs to use update linear algebra fglm functions\n"); exit(1); } /* block-size in data->res */ /* to store the terms we need */ const szmat_t block_size = bsz; fglm_param_set_prime(param, prime); const long sz = matrix->ncols * matrix->nrows; const long nb = initialize_fglm_data(matrix, data_fglm, prime, sz, block_size); if(info_level){ fprintf(stderr, "[%u, %u], Non trivial / Trivial = %.2f%%\n", matrix->ncols, matrix->nrows, 100*((double)matrix->nrows / (double)matrix->ncols)); fprintf(stderr, "Density of non-trivial part %.2f%%\n", 100-100*(float)nb/(float)sz); } const ulong dimquot = (matrix->ncols); #if DEBUGFGLM > 0 print_vec(stderr, data_fglm->vecinit, matrix->ncols); print_vec(stderr, data_fglm->res, 2 * block_size * matrix->ncols); fprintf(stderr, "\n"); #endif double st_fglm = realtime(); ////////////////////////////////////////////////////////////////// /* generate_sequence(matrix, data_fglm, block_size, dimquot, prime, st); */ generate_sequence_verif(matrix, data_fglm, block_size, dimquot, squvars, linvars, nvars, prime, st); ////////////////////////////////////////////////////////////////// if(info_level){ double nops = 2 * (matrix->nrows/ 1000.0) * (matrix->ncols / 1000.0) * (matrix->ncols / 1000.0); double rt_fglm = realtime()-st_fglm; fprintf(stderr, "Time spent to generate sequence (elapsed): %.2f sec (%.2f Gops/sec)\n", rt_fglm, nops / rt_fglm); } st_fglm = realtime(); fglm_bms_data_set_prime(data_bms, prime); long dim = 0; compute_minpoly(param, data_fglm, data_bms, dimquot, linvars, lineqs, nvars, &dim, info_level); if(info_level){ fprintf(stderr, "Time spent to compute eliminating polynomial (elapsed): %.2f sec\n", realtime()-st_fglm); } if(param->elim->length-1 != deg_init){ fprintf(stderr, "Warning: Degree of elim poly = %ld\n", param->elim->length-1); return 1; } if (dimquot == dim) { if(compute_parametrizations(param, data_fglm, data_bms, dim, dimquot, block_size, nlins, linvars, lineqs, nvars) == 0){ fprintf(stderr, "Matrix is not invertible (there should be a bug)\n"); exit(1); } } else { /* parametrization of the radical */ compute_parametrizations_non_shape_position_case(param, data_fglm, data_bms, dimquot, block_size, nlins, linvars, lineqs, squvars, nvars, prime, 1); } return 0; } static inline void guess_minpoly_colon(param_t *param, fglm_data_t *data, fglm_bms_data_t *data_bms, long dimquot, long tentative_degree, nvars_t *linvars, uint32_t *lineqs, long nvars, long *dim, int info_level){ compute_elim_poly(data, data_bms, tentative_degree); if(dimquot > 1){ *dim = make_square_free_elim_poly_colon(param, data_bms, dimquot, info_level); } else{ nmod_poly_fit_length(param->elim, 2); param->elim->length = 2; param->elim->coeffs[1] = 1; param->elim->coeffs[0] = lineqs[nvars*(nvars+1)-1]; *dim = 1; } } static inline void guess_sequence_colon(sp_matfglmcol_t *matrix, fglm_data_t * data, CF_t * leftvec, CF_t ** leftvecparam, szmat_t block_size, long dimquot, mod_t prime, param_t * param, fglm_bms_data_t * data_bms, nvars_t *linvars, uint32_t *lineqs, const long nvars, long *dim_ptr, const int info_level, md_t *st){ /* printf ("modulo %d\n",prime); */ /* printf ("size %d\n",matrix->ncols); */ /* printf ("leftvec\n"); */ /* print_vec(stdout, leftvec, matrix->ncols); */ /* printf ("rightvec\n"); */ /* print_vec(stdout, data->vecinit, matrix->ncols); */ uint32_t RED_32 = ((uint64_t)2<<31) % prime; #if DEBUGFGLM > 2 fprintf(stderr, "RED_32 = %u\n", RED_32); #endif uint32_t RED_64 = ((uint64_t)1<<63) % prime; RED_64 = (RED_64*2) % prime; #if DEBUGFGLM > 2 fprintf(stderr, "RED_64 = %u\n", RED_64); #endif uint32_t preinv = 2^(62) % prime; uint32_t pi1 = ((uint64_t)pow(2, 32)) / RED_64; uint32_t pi2 = (uint64_t)pow(2, 32) / RED_32; uint64_t * data_backup = (uint64_t *) malloc (2 * matrix->ncols * sizeof(uint64_t)); uint64_t acc = 0; uint64_t * accparam = (uint64_t *) calloc (2 * (nvars-1),sizeof(uint64_t)); for(szmat_t j = 0; j < matrix->ncols; j++){ acc = (acc + (((uint64_t)leftvec[j]) * data->vecinit[j])) % prime; for (szmat_t k = 1; k < block_size /*2*(nvars-1)*/; k++) { accparam[k-1] = (accparam[k-1] + (((uint64_t)leftvecparam[k-1][j]) * data->vecinit[j])) % prime; } } data->res[0] = acc; for (szmat_t k = 1; k < block_size; k++) { data->res[k] = accparam[k-1]; } data->pts[0] = acc; data_backup[0] = acc; szmat_t i = 1; szmat_t tentative_degree = MIN (4,matrix->ncols); /* printf ("tentative degree = %d\n",tentative_degree); */ while (i <= 2*tentative_degree-1) { sparse_mat_fglm_colon_mult_vec(data->vvec, matrix, data->vecinit, data->vecmult, prime, RED_32, RED_64, preinv, pi1, pi2,st); /* printf ("sparse_mat\n"); */ #if DEBUGFGLM > 1 print_vec(stderr, data->vvec, matrix->ncols); #endif CF_t *tmp = data->vecinit; data->vecinit = data->vvec; data->vvec = tmp; /* data->res[i*block_size] = data->vecinit[0]; */ acc = 0; for (long k = 1; k < block_size/*2*(nvars-1)*/; k++) { accparam[k-1] = 0; } for(szmat_t j = 0; j < matrix->ncols; j++){ acc = (acc + (((uint64_t)leftvec[j]) * data->vecinit[j])) % prime; for (long k = 1; k < block_size /*2*(nvars-1)*/; k++) { accparam[k-1] = (accparam[k-1] + (((uint64_t)leftvecparam[k-1][j]) * data->vecinit[j])) % prime; } } data->res[i*block_size]= acc; for (szmat_t k = 1; k < block_size; k++) { data->res[i*block_size + k] = accparam[k-1]; } data->pts[i] = acc; data_backup[i] = acc; #if DEBUGFGLM > 1 print_vec(stdout, data->res, 2*block_size * matrix->ncols); #endif #if DEBUGFGLM > 2 fprintf(stderr, "res = "); print_vec(stdout, data->res+i*matrix->ncols, matrix->ncols); #endif if (i == 2*tentative_degree-1) { /* printf ("guessing min poly\n"); */ guess_minpoly_colon(param, data, data_bms, dimquot, tentative_degree, linvars, lineqs, nvars, dim_ptr, info_level); if (*dim_ptr < tentative_degree) { /* printf ("degree ok!\n"); */ free (data_backup); break; } else { nmod_berlekamp_massey_set_prime (data_bms->BMS,prime); memcpy (data->pts,data_backup,i * sizeof(CF_t)); tentative_degree = MIN (3 * (*dim_ptr),matrix->ncols); /* printf ("tentative degree = %d\n",tentative_degree); */ } } i++; } } #if 0 static inline void generate_sequence_colon(sp_matfglmcol_t *matrix, fglm_data_t * data, CF_t * leftvec, szmat_t block_size, long dimquot, mod_t prime, md_t *st){ uint32_t RED_32 = ((uint64_t)2<<31) % prime; #if DEBUGFGLM > 2 fprintf(stderr, "RED_32 = %u\n", RED_32); #endif uint32_t RED_64 = ((uint64_t)1<<63) % prime; RED_64 = (RED_64*2) % prime; #if DEBUGFGLM > 2 fprintf(stderr, "RED_64 = %u\n", RED_64); #endif uint32_t preinv = 2^(62) % prime; uint32_t pi1 = ((uint64_t)pow(2, 32)) / RED_64; uint32_t pi2 = (uint64_t)pow(2, 32) / RED_32; uint64_t acc = 0; for(szmat_t j = 0; j < matrix->ncols; j++){ acc = (acc + (((uint64_t)leftvec[j]) * data->vecinit[j])) % prime; } data->res[0]= acc; for(szmat_t i = 1; i < matrix->ncols; i++){ sparse_mat_fglm_colon_mult_vec(data->vvec, matrix, data->vecinit, data->vecmult, prime, RED_32, RED_64, preinv, pi1, pi2,st); #if DEBUGFGLM > 1 print_vec(stderr, data->vvec, matrix->ncols); #endif CF_t *tmp = data->vecinit; data->vecinit = data->vvec; data->vvec = tmp; /* data->res[i*block_size] = data->vecinit[0]; */ acc = 0; for(szmat_t j = 0; j < matrix->ncols; j++){ acc = (acc + (((uint64_t)leftvec[j]) * data->vecinit[j])) % prime; } data->res[i*block_size]= acc; for(szmat_t j = 1; j < block_size; j++){ data->res[j+i*block_size] = data->vecinit[j+1]; } #if DEBUGFGLM > 1 print_vec(stdout, data->res, 2*block_size * matrix->ncols); #endif #if DEBUGFGLM > 2 fprintf(stderr, "res = "); print_vec(stdout, data->res+i*matrix->ncols, matrix->ncols); #endif } for(szmat_t i = matrix->ncols; i < 2*matrix->ncols; i++){ sparse_mat_fglm_colon_mult_vec(data->vvec, matrix, data->vecinit, data->vecmult, prime, RED_32, RED_64, preinv, pi1, pi2,st); #if DEBUGFGLM > 1 print_vec(stderr, data->vvec, matrix->ncols); #endif CF_t *tmp = data->vecinit; data->vecinit = data->vvec; data->vvec = tmp; /* data->res[i*block_size] = data->vecinit[0]; */ acc = 0; for(szmat_t j = 0; j < matrix->ncols; j++){ acc = (acc + (((uint64_t)leftvec[j]) * data->vecinit[j])) % prime; } data->res[i*block_size]= acc; #if DEBUGFGLM > 1 print_vec(stdout, data->res, 2*block_size * matrix->ncols); #endif #if DEBUGFGLM > 2 fprintf(stderr, "res = "); print_vec(stdout, data->res+i*matrix->ncols, matrix->ncols); #endif } #if DEBUGFGLM > 0 // print_vec(stdout, data->res, 2*block_size * matrix->ncols); #endif //now res contains our generating sequence for(ulong i = 0; i < 2 * dimquot; i++){ data->pts[i] = data->res[i*block_size]; } } #endif param_t *nmod_fglm_guess_colon(sp_matfglmcol_t *matrix, const mod_t prime, CF_t *leftvec, CF_t **leftvecparam, const nvars_t nvars, const nvars_t nlins, nvars_t *linvars, uint32_t *lineqs, nvars_t *squvars, const int info_level, md_t *st){ #if DEBUGFGLM > 0 fprintf(stderr, "prime = %u\n", prime); #endif #if DEBUGFGLM >= 1 FILE *fmat = fopen("/tmp/matrix.fglm", "w"); display_fglm_colon_matrix(fmat, matrix); fclose(fmat); #endif /* 1147878294 */ if(prime>=1518500213){ fprintf(stderr, "Prime %u is too large.\n", prime); fprintf(stderr, "One needs to use update linear algebra fglm functions\n"); return NULL; } /* szmat_t block_size = nvars-nlins; //taille de bloc dans data->res */ szmat_t block_size = 2*nvars-1; //taille de bloc dans data->res /* for storing sequences terms we need to keep */ fglm_data_t *data = allocate_fglm_data(matrix->nrows, matrix->ncols, 2*nvars-1); param_t *param = allocate_fglm_param(prime, nvars); long sz = matrix->ncols * matrix->nrows; long nb = initialize_fglm_colon_data(matrix, data, prime, sz, block_size); if(info_level){ fprintf(stderr, "[%u, %u], Non trivial / Trivial = %.2f%%\n", matrix->ncols, matrix->nrows, 100*((double)matrix->nrows / (double)matrix->ncols)); fprintf(stderr, "Density of non-trivial part %.2f%%\n", 100-100*(float)nb/(float)sz); } ulong dimquot = (matrix->ncols); //Berlekamp-Massey data fglm_bms_data_t *data_bms = allocate_fglm_bms_data(dimquot, prime); #if DEBUGFGLM > 1 print_vec(stderr, data->vecinit, matrix->ncols); print_vec(stderr, data->res, 2 * block_size * matrix->ncols); fprintf(stderr, "\n"); #endif long dim=0; double st0 = omp_get_wtime(); ////////////////////////////////////////////////////////////////// /* generate_sequence(matrix, data, block_size, dimquot, prime, st); */ /* generate_sequence_verif(matrix, data, block_size, dimquot, */ /* squvars, linvars, nvars, prime, st); */ /* printf ("guess\n"); */ guess_sequence_colon(matrix, data, leftvec, leftvecparam, block_size, dimquot, prime, param, data_bms, linvars, lineqs, nvars, &dim, info_level, st); /* printf ("guessed\n"); */ ////////////////////////////////////////////////////////////////// if(info_level){ fprintf(stderr,"Time spent to generate sequence\n"); fprintf(stderr,"and compute eliminating polynomial (elapsed): %.2f sec\n", omp_get_wtime()-st0); fprintf(stderr, "Elimination done.\n"); } /* nmod_poly_fprint_pretty(stderr, param->elim, "x"); fprintf (stdout,"\n"); */ ////////////////////////////////////////////////////////////////// // Now we compute the parametrizations of the radical int right_param= compute_parametrizations_colon(param, data, data_bms, dimquot, block_size, nlins, linvars, lineqs, squvars, nvars, prime, 1); if (right_param == 0) { fprintf(stderr, "Matrix is not invertible (there should be a bug)\n"); free_fglm_bms_data(data_bms); free_fglm_data(data); return NULL; } else if (right_param == 1) { fprintf(stderr, "Ideal might have no correct parametrization\n"); } else if (right_param == 2) { fprintf(stderr, "Only the first parametrization of "); fprintf (stderr,"the ideal seems correct\n"); } else if (right_param < nvars) { fprintf(stderr, "Only the first %d parametrizations of ",right_param-1); fprintf(stderr, "the ideal seem correct\n"); } else { fprintf(stderr, "All the parametrizations of "); fprintf(stderr, "the ideal seem correct\n"); } if(info_level){ fprintf(stderr, "Time spent to compute parametrizations (elapsed): %.2f sec\n", omp_get_wtime()-st0); fprintf(stderr, "Parametrizations done.\n"); } free_fglm_bms_data(data_bms); free_fglm_data(data); /* printf ("free fglm\n"); */ return param; } msolve-0.6.5/src/fglm/inner-product.c000066400000000000000000000630701456710632100175130ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include #include #include #ifdef HAVE_AVX2 #include #define AVX2LOAD(A) _mm256_load_si256((__m256i*)(A)) #define AVX2LOADU(A) _mm256_loadu_si256((__m256i*)(A)) #define AVX2STORE(res,A) _mm256_store_si256((__m256i*)(res),A); #define AVX2STOREU(res,A) _mm256_storeu_si256((__m256i*)(res),A); #define AVX2SETZERO() _mm256_setzero_si256() #define AVX2SET1_64(A0) _mm256_set1_epi64x(A0) #define AVX2AND_(A,B) _mm256_and_si256(A,B) #define AVX2ADD_64(A,B) _mm256_add_epi64(A,B) #define AVX2MUL(A,B) _mm256_mul_epu32(A,B) #define AVX2SRLI_64(A,i) _mm256_srli_epi64(A,i) #endif /* Matrix-vector product in GF(p), with p on 32 bits. */ /* Euclidean division of LENGTH by 8 */ /* LENGTH/8 */ #define LENGTHQ(l) (l>>3) /* LENGTH%8 */ #define LENGTHR(l) (l&7) #define LENGTHQ8(l) (l / 32) #define LENGTHR8(l) (l%32) #define LENGTHQ14(l) (l / 56) #define LENGTHR14(l) (l%56) //-1 sur 32 bits #define MONE32 ((uint32_t)0xFFFFFFFF) #define ALIGNED32_MALLOC(p,type,nmemb,size) p=(type)_mm_malloc(nmemb*size,32); #define ALIGNED32_CALLOC(p,type,nmemb,size) \ ALIGNED32_MALLOC(p,type,nmemb,size); \ memset((void*)p,0,nmemb*size); #define ALIGNED_FREE(p) _mm_free(p); #define ALIGNED32 __attribute__((aligned(32))) /* Faster when set to 1 */ //#define IS_ALIGNED_TMP 1 /* Requirement: the vector is aligned on 32 bytes */ //#define IS_ALIGNED_VECTOR 1 /* Requirement: the matrix is aligned on 32 bytes */ //#define IS_ALIGNED_MATRIX 1 #include #define PRINT_U32(a) printf("%"PRIu32,a); /* /\* */ /* Barrett reduction */ /* 2^30 < p < 2^31 */ /* r=31 and n=32 */ /* alpha = 2^(n-1) = 2^31, t=n=32, s=r-1=30 */ /* preinv = q = floor( 2^(s+t) / p ) */ static inline uint32_t MODRED32(const uint64_t n, const uint32_t p, const uint32_t preinv){ const uint32_t s = 30; const uint32_t t = 32; const uint64_t t1 = n >> s; const uint64_t t2 = (t1 * preinv) >> t; int64_t r = n - t2 * p; (r >= p) ? r -= p : r; (r >= p) ? r -= p : r; return r; } static inline uint32_t ADDMODRED32(uint64_t a, uint64_t b, const uint32_t p, const uint32_t preinv) { const long neg = p - a; return (neg > b) ? MODRED32((a + b), p, preinv) : MODRED32((b - neg), p, preinv); } static inline uint32_t mul_mod_barrett(const uint32_t x, const uint32_t y, const uint32_t p, const uint32_t pi){ const int n = 32; uint32_t c = (x * ((int64_t) pi)) >> n; int64_t d = ((int64_t) x) * y - ((int64_t) c) * p; return (d >= p) ? d - p : d; } static inline void non_avx_matrix_vector_product(uint32_t* vec_res, const uint32_t* mat, const uint32_t* vec, const uint32_t ncols, const uint32_t nrows, const uint32_t PRIME, const uint32_t RED_32, const uint32_t RED_64) { uint32_t i, j; int64_t prod1, prod2, prod3, prod4; const int64_t modsquare = (int64_t)PRIME*PRIME; j = 0; if (nrows >= 4) { for (j = 0; j < nrows-3; j += 4) { i = 0; prod1 = 0; prod2 = 0; prod3 = 0; prod4 = 0; if (ncols >= 8) { while (i < ncols-7) { prod1 -= (int64_t)mat[j*ncols+i] * vec[i]; prod2 -= (int64_t)mat[(j+1)*ncols+i] * vec[i]; prod3 -= (int64_t)mat[(j+2)*ncols+i] * vec[i]; prod4 -= (int64_t)mat[(j+3)*ncols+i] * vec[i]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+1] * vec[i+1]; prod2 -= (int64_t)mat[(j+1)*ncols+i+1] * vec[i+1]; prod3 -= (int64_t)mat[(j+2)*ncols+i+1] * vec[i+1]; prod4 -= (int64_t)mat[(j+3)*ncols+i+1] * vec[i+1]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+2] * vec[i+2]; prod2 -= (int64_t)mat[(j+1)*ncols+i+2] * vec[i+2]; prod3 -= (int64_t)mat[(j+2)*ncols+i+2] * vec[i+2]; prod4 -= (int64_t)mat[(j+3)*ncols+i+2] * vec[i+2]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+3] * vec[i+3]; prod2 -= (int64_t)mat[(j+1)*ncols+i+3] * vec[i+3]; prod3 -= (int64_t)mat[(j+2)*ncols+i+3] * vec[i+3]; prod4 -= (int64_t)mat[(j+3)*ncols+i+3] * vec[i+3]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+4] * vec[i+4]; prod2 -= (int64_t)mat[(j+1)*ncols+i+4] * vec[i+4]; prod3 -= (int64_t)mat[(j+2)*ncols+i+4] * vec[i+4]; prod4 -= (int64_t)mat[(j+3)*ncols+i+4] * vec[i+4]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+5] * vec[i+5]; prod2 -= (int64_t)mat[(j+1)*ncols+i+5] * vec[i+5]; prod3 -= (int64_t)mat[(j+2)*ncols+i+5] * vec[i+5]; prod4 -= (int64_t)mat[(j+3)*ncols+i+5] * vec[i+5]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+6] * vec[i+6]; prod2 -= (int64_t)mat[(j+1)*ncols+i+6] * vec[i+6]; prod3 -= (int64_t)mat[(j+2)*ncols+i+6] * vec[i+6]; prod4 -= (int64_t)mat[(j+3)*ncols+i+6] * vec[i+6]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+7] * vec[i+7]; prod2 -= (int64_t)mat[(j+1)*ncols+i+7] * vec[i+7]; prod3 -= (int64_t)mat[(j+2)*ncols+i+7] * vec[i+7]; prod4 -= (int64_t)mat[(j+3)*ncols+i+7] * vec[i+7]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; i += 8; } } while (i < ncols) { prod1 -= (int64_t)mat[j*ncols+i] * vec[i]; prod2 -= (int64_t)mat[(j+1)*ncols+i] * vec[i]; prod3 -= (int64_t)mat[(j+2)*ncols+i] * vec[i]; prod4 -= (int64_t)mat[(j+3)*ncols+i] * vec[i]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; i += 1; } /* enusre prod being positive */ prod1 = -prod1; prod1 += (prod1 >> 63) & modsquare; prod2 = -prod2; prod2 += (prod2 >> 63) & modsquare; prod3 = -prod3; prod3 += (prod3 >> 63) & modsquare; prod4 = -prod4; prod4 += (prod4 >> 63) & modsquare; vec_res[j] = (uint32_t)(prod1 % PRIME); vec_res[j+1] = (uint32_t)(prod2 % PRIME); vec_res[j+2] = (uint32_t)(prod3 % PRIME); vec_res[j+3] = (uint32_t)(prod4 % PRIME); } } for (; j < nrows; ++j) { i = 0; prod1 = 0; if (ncols >= 8) { while (i < ncols-7) { prod1 -= (int64_t)mat[j*ncols+i] * vec[i]; prod1 += ((prod1 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+1] * vec[i+1]; prod1 += ((prod1 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+2] * vec[i+2]; prod1 += ((prod1 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+3] * vec[i+3]; prod1 += ((prod1 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+4] * vec[i+4]; prod1 += ((prod1 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+5] * vec[i+5]; prod1 += ((prod1 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+6] * vec[i+6]; prod1 += ((prod1 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+7] * vec[i+7]; prod1 += ((prod1 >> 63)) & modsquare; prod1 += ((prod1 >> 63)) & modsquare; i += 8; } } while (i < ncols) { prod1 -= (int64_t)mat[j*ncols+i] * vec[i]; prod1 += ((prod1 >> 63)) & modsquare; i += 1; } /* enusre prod being positive */ prod1 = -prod1; prod1 += (prod1 >> 63) & modsquare; vec_res[j] = (uint32_t)(prod1 % PRIME); } } #ifdef HAVE_AVX2 static inline void matrix_vector_product(uint32_t* vec_res, const uint32_t* mat, const uint32_t* vec, const uint32_t ncols, const uint32_t nrows, const uint32_t PRIME, const uint32_t RED_32, const uint32_t RED_64) { __m256i acc_low,acc_high,prod,mask,vec8,mat8; #if IS_ALIGNED_TMP uint64_t acc4x64[8] ALIGNED32; //#if LENGTHR(ncols) uint32_t vecr[8] ALIGNED32,matr[8] ALIGNED32; //#endif #else uint64_t acc4x64[8]; //#if LENGTHR(ncols) uint32_t vecr[8],matr[8]; //#endif #endif uint64_t acc64; const uint32_t *vec_cp; unsigned int i,j; //mask pour recuperer les parties basses mask=AVX2SET1_64(MONE32); if(LENGTHR(ncols)){ for(i=LENGTHR(ncols);i<8;++i) { matr[i]=0; vecr[i]=0; } } /* For each row of the matrix, we compute a dot product */ for(j=0;j1){ /* four 32-bits mul, higher parts */ prod=AVX2MUL(AVX2SRLI_64(mat8,32),AVX2SRLI_64(vec8,32)); acc_low=AVX2ADD_64(acc_low,AVX2AND_(prod,mask)); acc_high=AVX2ADD_64(acc_high,AVX2SRLI_64(prod,32)); } } #if IS_ALIGNED_TMP AVX2STORE(acc4x64,acc_low); AVX2STORE(acc4x64+4,acc_high); #else AVX2STOREU(acc4x64,acc_low); AVX2STOREU(acc4x64+4,acc_high); #endif /* Reduction */ acc64=0; for(i=0;i<4;++i){ //partie haute du registre haut (2^64 ->2^95) acc4x64[i]+=((acc4x64[i+4]>>32)*RED_64)%PRIME; //partie basse du registre haut (2^32->2^63) acc4x64[i]+=((acc4x64[i+4]&((uint64_t)0xFFFFFFFF))*RED_32)%PRIME; // acc64+=acc4x64[i]%PRIME; acc64+=acc4x64[i]; } *vec_res=acc64%PRIME; ++vec_res; } } static inline void _2mul_new_matrix_vector_product(uint32_t* vec_res, const uint32_t* mat, const uint32_t* vec, const uint32_t ncols, const uint32_t nrows, const uint32_t PRIME, const uint32_t RED_32, const uint32_t RED_64) { __m256i acc_low,acc_high,mask,vec8,mat8,prod,prod1,prod2; #if IS_ALIGNED_TMP uint64_t acc4x64[8] ALIGNED32; //#if LENGTHR(ncols) uint32_t vecr[8] ALIGNED32,matr[8] ALIGNED32; //#endif #else uint64_t acc4x64[8]; //#if LENGTHR(ncols) uint32_t vecr[8],matr[8]; //#endif #endif uint64_t acc64; const uint32_t *vec_cp; unsigned int i,j; //mask pour recuperer les parties basses mask=AVX2SET1_64(MONE32); if(LENGTHR(ncols)){ for(i=LENGTHR(ncols);i<8;++i) { matr[i]=0; vecr[i]=0; } } /* For each row of the matrix, we compute a dot product */ for(j=0;j1){ /* four 32-bits mul, higher parts */ prod=AVX2MUL(AVX2SRLI_64(mat8,32),AVX2SRLI_64(vec8,32)); acc_low=AVX2ADD_64(acc_low,AVX2AND_(prod,mask)); acc_high=AVX2ADD_64(acc_high,AVX2SRLI_64(prod,32)); } } #if IS_ALIGNED_TMP AVX2STORE(acc4x64,acc_low); AVX2STORE(acc4x64+4,acc_high); #else AVX2STOREU(acc4x64,acc_low); AVX2STOREU(acc4x64+4,acc_high); #endif /* Reduction */ acc64=0; for(i=0;i<4;++i){ //partie haute du registre haut (2^64 ->2^95) acc4x64[i]+=((acc4x64[i+4]>>32)*RED_64)%PRIME; //partie basse du registre haut (2^32->2^63) acc4x64[i]+=((acc4x64[i+4]&((uint64_t)0xFFFFFFFF))*RED_32)%PRIME; // acc64+=acc4x64[i]%PRIME; acc64+=acc4x64[i]; } *vec_res=acc64%PRIME; ++vec_res; } } static inline void _4mul_new_matrix_vector_product(uint32_t* vec_res, const uint32_t* mat, const uint32_t* vec, const uint32_t ncols, const uint32_t nrows, const uint32_t PRIME, const uint32_t RED_32, const uint32_t RED_64) { __m256i acc_low,acc_high,mask,vec8,mat8; __m256i prod,prod1,prod2,prod3,prod4; #if IS_ALIGNED_TMP uint64_t acc4x64[8] ALIGNED32; //#if LENGTHR(ncols) uint32_t vecr[8] ALIGNED32,matr[8] ALIGNED32; //#endif #else uint64_t acc4x64[8]; //#if LENGTHR(ncols) uint32_t vecr[8],matr[8]; //#endif #endif uint64_t acc64; const uint32_t *vec_cp; unsigned int i,j; //mask pour recuperer les parties basses mask=AVX2SET1_64(MONE32); if(LENGTHR(ncols)){ for(i=LENGTHR(ncols);i<8;++i) { matr[i]=0; vecr[i]=0; } } /* For each row of the matrix, we compute a dot product */ for(j=0;j1){ /* four 32-bits mul, higher parts */ prod=AVX2MUL(AVX2SRLI_64(mat8,32),AVX2SRLI_64(vec8,32)); acc_low=AVX2ADD_64(acc_low,AVX2AND_(prod,mask)); acc_high=AVX2ADD_64(acc_high,AVX2SRLI_64(prod,32)); } } #if IS_ALIGNED_TMP AVX2STORE(acc4x64,acc_low); AVX2STORE(acc4x64+4,acc_high); #else AVX2STOREU(acc4x64,acc_low); AVX2STOREU(acc4x64+4,acc_high); #endif /* Reduction */ acc64=0; for(i=0;i<4;++i){ //partie haute du registre haut (2^64 ->2^95) acc4x64[i]+=((acc4x64[i+4]>>32)*RED_64)%PRIME; //partie basse du registre haut (2^32->2^63) acc4x64[i]+=((acc4x64[i+4]&((uint64_t)0xFFFFFFFF))*RED_32)%PRIME; // acc64+=acc4x64[i]%PRIME; acc64+=acc4x64[i]; } *vec_res=acc64%PRIME; ++vec_res; } } /** AVX2-based matrix vector product **/ static inline void _8mul_matrix_vector_product(uint32_t* vec_res, const uint32_t* mat, const uint32_t* vec, const uint32_t *dst, const uint32_t ncols, const uint32_t nrows, const uint32_t PRIME, const uint32_t RED_32, const uint32_t RED_64, const uint32_t preinv){ __m256i acc_low,acc_high,mask,vec8,mat8; __m256i prod1,prod2; __m256i res1; #if IS_ALIGNED_TMP uint64_t acc4x64[8] ALIGNED32; #else uint64_t acc4x64[8]; #endif uint64_t acc64; const uint32_t *vec_cp; unsigned int i,j; //mask pour recuperer les parties basses mask=AVX2SET1_64(MONE32); const long quo0 = LENGTHQ8(ncols); const long rem0 = LENGTHR8(ncols); /* For each row of the matrix, we compute a dot product */ for(j = 0; j < nrows; ++j){ vec_cp=vec; acc_low=AVX2SETZERO(); acc_high=AVX2SETZERO(); long local_ncols, quo, rem; if(dst[j] != 0){ local_ncols = ncols - dst[j]; quo = LENGTHQ8(local_ncols); rem = LENGTHR8(local_ncols); } else{ local_ncols = ncols; quo = quo0; rem = rem0; } const long bs = quo; /* Accumulation */ for(i = 0 ; i < bs; ++i){ #if IS_ALIGNED_MATRIX mat8=AVX2LOAD(mat); #else mat8=AVX2LOADU(mat); #endif #if IS_ALIGNED_VECTOR vec8=AVX2LOAD(vec_cp); #else vec8=AVX2LOADU(vec_cp); #endif /* four 32-bits mul, lower parts */ /* four 32-bits mul, higher parts */ prod1=AVX2MUL(mat8,vec8); prod2= AVX2MUL(AVX2SRLI_64(mat8,32),AVX2SRLI_64(vec8,32)); res1 = prod1 + prod2; mat+=8; vec_cp+=8; #if IS_ALIGNED_MATRIX mat8=AVX2LOAD(mat); #else mat8=AVX2LOADU(mat); #endif #if IS_ALIGNED_VECTOR vec8=AVX2LOAD(vec_cp); #else vec8=AVX2LOADU(vec_cp); #endif prod1=AVX2MUL(mat8,vec8); prod2= AVX2MUL(AVX2SRLI_64(mat8,32),AVX2SRLI_64(vec8,32)); res1 += prod1 + prod2; mat+=8; vec_cp+=8; #if IS_ALIGNED_MATRIX mat8=AVX2LOAD(mat); #else mat8=AVX2LOADU(mat); #endif #if IS_ALIGNED_VECTOR vec8=AVX2LOAD(vec_cp); #else vec8=AVX2LOADU(vec_cp); #endif prod1=AVX2MUL(mat8,vec8); prod2= AVX2MUL(AVX2SRLI_64(mat8,32),AVX2SRLI_64(vec8,32)); res1 += prod1 + prod2; mat+=8; vec_cp+=8; #if IS_ALIGNED_MATRIX mat8=AVX2LOAD(mat); #else mat8=AVX2LOADU(mat); #endif #if IS_ALIGNED_VECTOR vec8=AVX2LOAD(vec_cp); #else vec8=AVX2LOADU(vec_cp); #endif prod1=AVX2MUL(mat8,vec8); prod2= AVX2MUL(AVX2SRLI_64(mat8,32),AVX2SRLI_64(vec8,32)); res1 += prod1 + prod2; mat+=8; vec_cp+=8; acc_low=AVX2ADD_64(acc_low,AVX2AND_(res1,mask)); acc_high=AVX2ADD_64(acc_high,AVX2SRLI_64(res1,32)); } #if IS_ALIGNED_TMP AVX2STORE(acc4x64,acc_low); AVX2STORE(acc4x64+4,acc_high); #else AVX2STOREU(acc4x64,acc_low); AVX2STOREU(acc4x64+4,acc_high); #endif /* Reduction */ acc64=0; for(i=0;i<4;++i){ //partie haute du registre haut (2^64 ->2^95) acc4x64[i]+=((acc4x64[i+4]>>32)*RED_64)%PRIME; //partie basse du registre haut (2^32->2^63) acc4x64[i]+=((acc4x64[i+4]&((uint64_t)0xFFFFFFFF))*RED_32)%PRIME; acc64+=acc4x64[i]%PRIME; //acc64+=acc4x64[i]; } /* *vec_res=MODRED32(acc64, PRIME, preinv); */ *vec_res=acc64%PRIME; long tmp = 0; for(long k = 0; k < rem; k++){ tmp += ((long)mat[k] * (long)vec_cp[k]) % PRIME; } *vec_res += tmp % PRIME; mat+=(rem + dst[j]); ++vec_res; } } #endif msolve-0.6.5/src/fglm/libfglm.h000066400000000000000000000013731456710632100163410ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "fglm.h" msolve-0.6.5/src/fglm/linalg-fglm.c000066400000000000000000000615421456710632100171150ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include #include #include #ifdef HAVE_AVX2 #include #define AVX2LOAD(A) _mm256_load_si256((__m256i*)(A)) #define AVX2LOADU(A) _mm256_loadu_si256((__m256i*)(A)) #define AVX2STORE(res,A) _mm256_store_si256((__m256i*)(res),A); #define AVX2STOREU(res,A) _mm256_storeu_si256((__m256i*)(res),A); #define AVX2SETZERO() _mm256_setzero_si256() #define AVX2SET1_64(A0) _mm256_set1_epi64x(A0) #define AVX2AND_(A,B) _mm256_and_si256(A,B) #define AVX2ADD_64(A,B) _mm256_add_epi64(A,B) #define AVX2MUL(A,B) _mm256_mul_epu32(A,B) #define AVX2SRLI_64(A,i) _mm256_srli_epi64(A,i) #endif /* Matrix-vector product in GF(p), with p on 32 bits. */ /* Euclidean division of LENGTH by 8 */ /* LENGTH/8 */ #define LENGTHQ(l) (l>>3) /* LENGTH%8 */ #define LENGTHR(l) (l&7) #define LENGTHQ8(l) (l / 32) #define LENGTHR8(l) (l%32) #define LENGTHQ14(l) (l / 56) #define LENGTHR14(l) (l%56) //-1 sur 32 bits #define MONE32 ((uint32_t)0xFFFFFFFF) #define ALIGNED32_MALLOC(p,type,nmemb,size) p=(type)_mm_malloc(nmemb*size,32); #define ALIGNED32_CALLOC(p,type,nmemb,size) \ ALIGNED32_MALLOC(p,type,nmemb,size); \ memset((void*)p,0,nmemb*size); #define ALIGNED_FREE(p) _mm_free(p); #define ALIGNED32 __attribute__((aligned(32))) /* Faster when set to 1 */ //#define IS_ALIGNED_TMP 1 /* Requirement: the vector is aligned on 32 bytes */ //#define IS_ALIGNED_VECTOR 1 /* Requirement: the matrix is aligned on 32 bytes */ //#define IS_ALIGNED_MATRIX 1 #include #define PRINT_U32(a) printf("%"PRIu32,a); static inline uint32_t mul_mod_barrett(const uint32_t x, const uint32_t y, const uint32_t p, const uint32_t pi){ const int n = 32; uint32_t c = (x * ((int64_t) pi)) >> n; int64_t d = ((int64_t) x) * y - ((int64_t) c) * p; return (d >= p) ? d - p : d; } static inline void non_avx_matrix_vector_product(uint32_t* vec_res, const uint32_t* mat, const uint32_t* vec, const uint32_t ncols, const uint32_t nrows, const uint32_t PRIME, const uint32_t RED_32, const uint32_t RED_64, md_t *st) { uint32_t i, j; int64_t prod1, prod2, prod3, prod4; const int64_t modsquare = (int64_t)PRIME*PRIME; j = 0; if (nrows >= 4) { for (j = 0; j < nrows-3; j += 4) { i = 0; prod1 = 0; prod2 = 0; prod3 = 0; prod4 = 0; if (ncols >= 8) { while (i < ncols-7) { prod1 -= (int64_t)mat[j*ncols+i] * vec[i]; prod2 -= (int64_t)mat[(j+1)*ncols+i] * vec[i]; prod3 -= (int64_t)mat[(j+2)*ncols+i] * vec[i]; prod4 -= (int64_t)mat[(j+3)*ncols+i] * vec[i]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+1] * vec[i+1]; prod2 -= (int64_t)mat[(j+1)*ncols+i+1] * vec[i+1]; prod3 -= (int64_t)mat[(j+2)*ncols+i+1] * vec[i+1]; prod4 -= (int64_t)mat[(j+3)*ncols+i+1] * vec[i+1]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+2] * vec[i+2]; prod2 -= (int64_t)mat[(j+1)*ncols+i+2] * vec[i+2]; prod3 -= (int64_t)mat[(j+2)*ncols+i+2] * vec[i+2]; prod4 -= (int64_t)mat[(j+3)*ncols+i+2] * vec[i+2]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+3] * vec[i+3]; prod2 -= (int64_t)mat[(j+1)*ncols+i+3] * vec[i+3]; prod3 -= (int64_t)mat[(j+2)*ncols+i+3] * vec[i+3]; prod4 -= (int64_t)mat[(j+3)*ncols+i+3] * vec[i+3]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+4] * vec[i+4]; prod2 -= (int64_t)mat[(j+1)*ncols+i+4] * vec[i+4]; prod3 -= (int64_t)mat[(j+2)*ncols+i+4] * vec[i+4]; prod4 -= (int64_t)mat[(j+3)*ncols+i+4] * vec[i+4]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+5] * vec[i+5]; prod2 -= (int64_t)mat[(j+1)*ncols+i+5] * vec[i+5]; prod3 -= (int64_t)mat[(j+2)*ncols+i+5] * vec[i+5]; prod4 -= (int64_t)mat[(j+3)*ncols+i+5] * vec[i+5]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+6] * vec[i+6]; prod2 -= (int64_t)mat[(j+1)*ncols+i+6] * vec[i+6]; prod3 -= (int64_t)mat[(j+2)*ncols+i+6] * vec[i+6]; prod4 -= (int64_t)mat[(j+3)*ncols+i+6] * vec[i+6]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+7] * vec[i+7]; prod2 -= (int64_t)mat[(j+1)*ncols+i+7] * vec[i+7]; prod3 -= (int64_t)mat[(j+2)*ncols+i+7] * vec[i+7]; prod4 -= (int64_t)mat[(j+3)*ncols+i+7] * vec[i+7]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; i += 8; } } while (i < ncols) { prod1 -= (int64_t)mat[j*ncols+i] * vec[i]; prod2 -= (int64_t)mat[(j+1)*ncols+i] * vec[i]; prod3 -= (int64_t)mat[(j+2)*ncols+i] * vec[i]; prod4 -= (int64_t)mat[(j+3)*ncols+i] * vec[i]; prod1 += ((prod1 >> 63)) & modsquare; prod2 += ((prod2 >> 63)) & modsquare; prod3 += ((prod3 >> 63)) & modsquare; prod4 += ((prod4 >> 63)) & modsquare; i += 1; } /* ensure prod being positive */ prod1 = -prod1; prod1 += (prod1 >> 63) & modsquare; prod2 = -prod2; prod2 += (prod2 >> 63) & modsquare; prod3 = -prod3; prod3 += (prod3 >> 63) & modsquare; prod4 = -prod4; prod4 += (prod4 >> 63) & modsquare; vec_res[j] = (uint32_t)(prod1 % PRIME); vec_res[j+1] = (uint32_t)(prod2 % PRIME); vec_res[j+2] = (uint32_t)(prod3 % PRIME); vec_res[j+3] = (uint32_t)(prod4 % PRIME); } } for (; j < nrows; ++j) { i = 0; prod1 = 0; if (ncols >= 8) { while (i < ncols-7) { prod1 -= (int64_t)mat[j*ncols+i] * vec[i]; prod1 += ((prod1 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+1] * vec[i+1]; prod1 += ((prod1 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+2] * vec[i+2]; prod1 += ((prod1 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+3] * vec[i+3]; prod1 += ((prod1 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+4] * vec[i+4]; prod1 += ((prod1 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+5] * vec[i+5]; prod1 += ((prod1 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+6] * vec[i+6]; prod1 += ((prod1 >> 63)) & modsquare; prod1 -= (int64_t)mat[j*ncols+i+7] * vec[i+7]; prod1 += ((prod1 >> 63)) & modsquare; prod1 += ((prod1 >> 63)) & modsquare; i += 8; } } while (i < ncols) { prod1 -= (int64_t)mat[j*ncols+i] * vec[i]; prod1 += ((prod1 >> 63)) & modsquare; i += 1; } /* ensure prod being positive */ prod1 = -prod1; prod1 += (prod1 >> 63) & modsquare; vec_res[j] = (uint32_t)(prod1 % PRIME); } } #ifdef HAVE_AVX2 static inline void matrix_vector_product(uint32_t* vec_res, const uint32_t* mat, const uint32_t* vec, const uint32_t ncols, const uint32_t nrows, const uint32_t PRIME, const uint32_t RED_32, const uint32_t RED_64) { __m256i acc_low,acc_high,prod,mask,vec8,mat8; #if IS_ALIGNED_TMP uint64_t acc4x64[8] ALIGNED32; //#if LENGTHR(ncols) uint32_t vecr[8] ALIGNED32,matr[8] ALIGNED32; //#endif #else uint64_t acc4x64[8]; //#if LENGTHR(ncols) uint32_t vecr[8],matr[8]; //#endif #endif uint64_t acc64; const uint32_t *vec_cp; unsigned int i,j; //mask pour recuperer les parties basses mask=AVX2SET1_64(MONE32); if(LENGTHR(ncols)){ for(i=LENGTHR(ncols);i<8;++i) { matr[i]=0; vecr[i]=0; } } /* For each row of the matrix, we compute a dot product */ for(j=0;j1){ /* four 32-bits mul, higher parts */ prod=AVX2MUL(AVX2SRLI_64(mat8,32),AVX2SRLI_64(vec8,32)); acc_low=AVX2ADD_64(acc_low,AVX2AND_(prod,mask)); acc_high=AVX2ADD_64(acc_high,AVX2SRLI_64(prod,32)); } } #if IS_ALIGNED_TMP AVX2STORE(acc4x64,acc_low); AVX2STORE(acc4x64+4,acc_high); #else AVX2STOREU(acc4x64,acc_low); AVX2STOREU(acc4x64+4,acc_high); #endif /* Reduction */ acc64=0; for(i=0;i<4;++i){ //partie haute du registre haut (2^64 ->2^95) acc4x64[i]+=((acc4x64[i+4]>>32)*RED_64)%PRIME; //partie basse du registre haut (2^32->2^63) acc4x64[i]+=((acc4x64[i+4]&((uint64_t)0xFFFFFFFF))*RED_32)%PRIME; // acc64+=acc4x64[i]%PRIME; acc64+=acc4x64[i]; } *vec_res=acc64%PRIME; ++vec_res; } } static inline void _2mul_new_matrix_vector_product(uint32_t* vec_res, const uint32_t* mat, const uint32_t* vec, const uint32_t ncols, const uint32_t nrows, const uint32_t PRIME, const uint32_t RED_32, const uint32_t RED_64) { __m256i acc_low,acc_high,mask,vec8,mat8,prod,prod1,prod2; #if IS_ALIGNED_TMP uint64_t acc4x64[8] ALIGNED32; //#if LENGTHR(ncols) uint32_t vecr[8] ALIGNED32,matr[8] ALIGNED32; //#endif #else uint64_t acc4x64[8]; //#if LENGTHR(ncols) uint32_t vecr[8],matr[8]; //#endif #endif uint64_t acc64; const uint32_t *vec_cp; unsigned int i,j; //mask pour recuperer les parties basses mask=AVX2SET1_64(MONE32); if(LENGTHR(ncols)){ for(i=LENGTHR(ncols);i<8;++i) { matr[i]=0; vecr[i]=0; } } /* For each row of the matrix, we compute a dot product */ for(j=0;j1){ /* four 32-bits mul, higher parts */ prod=AVX2MUL(AVX2SRLI_64(mat8,32),AVX2SRLI_64(vec8,32)); acc_low=AVX2ADD_64(acc_low,AVX2AND_(prod,mask)); acc_high=AVX2ADD_64(acc_high,AVX2SRLI_64(prod,32)); } } #if IS_ALIGNED_TMP AVX2STORE(acc4x64,acc_low); AVX2STORE(acc4x64+4,acc_high); #else AVX2STOREU(acc4x64,acc_low); AVX2STOREU(acc4x64+4,acc_high); #endif /* Reduction */ acc64=0; for(i=0;i<4;++i){ //partie haute du registre haut (2^64 ->2^95) acc4x64[i]+=((acc4x64[i+4]>>32)*RED_64)%PRIME; //partie basse du registre haut (2^32->2^63) acc4x64[i]+=((acc4x64[i+4]&((uint64_t)0xFFFFFFFF))*RED_32)%PRIME; // acc64+=acc4x64[i]%PRIME; acc64+=acc4x64[i]; } *vec_res=acc64%PRIME; ++vec_res; } } static inline void _4mul_new_matrix_vector_product(uint32_t* vec_res, const uint32_t* mat, const uint32_t* vec, const uint32_t ncols, const uint32_t nrows, const uint32_t PRIME, const uint32_t RED_32, const uint32_t RED_64) { __m256i acc_low,acc_high,mask,vec8,mat8; __m256i prod,prod1,prod2,prod3,prod4; #if IS_ALIGNED_TMP uint64_t acc4x64[8] ALIGNED32; //#if LENGTHR(ncols) uint32_t vecr[8] ALIGNED32,matr[8] ALIGNED32; //#endif #else uint64_t acc4x64[8]; //#if LENGTHR(ncols) uint32_t vecr[8],matr[8]; //#endif #endif uint64_t acc64; const uint32_t *vec_cp; unsigned int i,j; //mask pour recuperer les parties basses mask=AVX2SET1_64(MONE32); if(LENGTHR(ncols)){ for(i=LENGTHR(ncols);i<8;++i) { matr[i]=0; vecr[i]=0; } } /* For each row of the matrix, we compute a dot product */ for(j=0;j1){ /* four 32-bits mul, higher parts */ prod=AVX2MUL(AVX2SRLI_64(mat8,32),AVX2SRLI_64(vec8,32)); acc_low=AVX2ADD_64(acc_low,AVX2AND_(prod,mask)); acc_high=AVX2ADD_64(acc_high,AVX2SRLI_64(prod,32)); } } #if IS_ALIGNED_TMP AVX2STORE(acc4x64,acc_low); AVX2STORE(acc4x64+4,acc_high); #else AVX2STOREU(acc4x64,acc_low); AVX2STOREU(acc4x64+4,acc_high); #endif /* Reduction */ acc64=0; for(i=0;i<4;++i){ //partie haute du registre haut (2^64 ->2^95) acc4x64[i]+=((acc4x64[i+4]>>32)*RED_64)%PRIME; //partie basse du registre haut (2^32->2^63) acc4x64[i]+=((acc4x64[i+4]&((uint64_t)0xFFFFFFFF))*RED_32)%PRIME; // acc64+=acc4x64[i]%PRIME; acc64+=acc4x64[i]; } *vec_res=acc64%PRIME; ++vec_res; } } /** AVX2-based matrix vector product **/ static inline void _8mul_matrix_vector_product(uint32_t* vec_res, const uint32_t* mat, const uint32_t* vec, const uint32_t *dst, const uint32_t ncols, const uint32_t nrows, const uint32_t PRIME, const uint32_t RED_32, const uint32_t RED_64, const uint32_t preinv, md_t *st){ //mask pour recuperer les parties basses __m256i mask=AVX2SET1_64(MONE32); const long quo0 = LENGTHQ8(ncols); const long rem0 = LENGTHR8(ncols); #pragma omp parallel num_threads (st->nthrds) { unsigned int i,j; #if IS_ALIGNED_TMP uint64_t acc4x64[8] ALIGNED32; #else uint64_t acc4x64[8]; #endif uint64_t acc64; __m256i acc_low,acc_high,vec8,mat8; __m256i prod1,prod2; __m256i res1; const uint32_t *vec_cp; const uint32_t *mat_cp; /* parallelization of the outer loop (rows) */ #pragma omp for /* For each row of the matrix, we compute a dot product */ for(j = 0; j < nrows; ++j){ vec_cp=vec; mat_cp=mat + j*ncols; acc_low=AVX2SETZERO(); acc_high=AVX2SETZERO(); long local_ncols, quo, rem; if(dst[j] != 0){ local_ncols = ncols - dst[j]; quo = LENGTHQ8(local_ncols); rem = LENGTHR8(local_ncols); } else{ local_ncols = ncols; quo = quo0; rem = rem0; } const long bs = quo; /* Accumulation */ for(i = 0 ; i < bs; ++i){ #if IS_ALIGNED_MATRIX mat8=AVX2LOAD(mat_cp); #else mat8=AVX2LOADU(mat_cp); #endif #if IS_ALIGNED_VECTOR vec8=AVX2LOAD(vec_cp); #else vec8=AVX2LOADU(vec_cp); #endif /* four 32-bits mul, lower parts */ /* four 32-bits mul, higher parts */ prod1=AVX2MUL(mat8,vec8); prod2= AVX2MUL(AVX2SRLI_64(mat8,32),AVX2SRLI_64(vec8,32)); res1 = prod1 + prod2; mat_cp+=8; vec_cp+=8; #if IS_ALIGNED_MATRIX mat8=AVX2LOAD(mat_cp); #else mat8=AVX2LOADU(mat_cp); #endif #if IS_ALIGNED_VECTOR vec8=AVX2LOAD(vec_cp); #else vec8=AVX2LOADU(vec_cp); #endif prod1=AVX2MUL(mat8,vec8); prod2= AVX2MUL(AVX2SRLI_64(mat8,32),AVX2SRLI_64(vec8,32)); res1 += prod1 + prod2; mat_cp+=8; vec_cp+=8; #if IS_ALIGNED_MATRIX mat8=AVX2LOAD(mat_cp); #else mat8=AVX2LOADU(mat_cp); #endif #if IS_ALIGNED_VECTOR vec8=AVX2LOAD(vec_cp); #else vec8=AVX2LOADU(vec_cp); #endif prod1=AVX2MUL(mat8,vec8); prod2= AVX2MUL(AVX2SRLI_64(mat8,32),AVX2SRLI_64(vec8,32)); res1 += prod1 + prod2; mat_cp+=8; vec_cp+=8; #if IS_ALIGNED_MATRIX mat8=AVX2LOAD(mat_cp); #else mat8=AVX2LOADU(mat_cp); #endif #if IS_ALIGNED_VECTOR vec8=AVX2LOAD(vec_cp); #else vec8=AVX2LOADU(vec_cp); #endif prod1=AVX2MUL(mat8,vec8); prod2= AVX2MUL(AVX2SRLI_64(mat8,32),AVX2SRLI_64(vec8,32)); res1 += prod1 + prod2; mat_cp+=8; vec_cp+=8; acc_low=AVX2ADD_64(acc_low,AVX2AND_(res1,mask)); acc_high=AVX2ADD_64(acc_high,AVX2SRLI_64(res1,32)); } #if IS_ALIGNED_TMP AVX2STORE(acc4x64,acc_low); AVX2STORE(acc4x64+4,acc_high); #else AVX2STOREU(acc4x64,acc_low); AVX2STOREU(acc4x64+4,acc_high); #endif /* Reduction */ acc64=0; for(i=0;i<4;++i){ //partie haute du registre haut (2^64 ->2^95) acc4x64[i]+=((acc4x64[i+4]>>32)*RED_64)%PRIME; //partie basse du registre haut (2^32->2^63) acc4x64[i]+=((acc4x64[i+4]&((uint64_t)0xFFFFFFFF))*RED_32)%PRIME; acc64+=acc4x64[i]%PRIME; } /* *vec_res[j]=MODRED32(acc64, PRIME, preinv); */ vec_res[j]=acc64%PRIME; long tmp = 0; for(long k = 0; k < rem; k++){ tmp += ((long)mat_cp[k] * (long)vec_cp[k]) % PRIME; } vec_res[j] = (vec_res[j] + tmp) % PRIME; } } } #endif msolve-0.6.5/src/fglm/matrix-mult.c000066400000000000000000000237311456710632100172050ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ //-1 sur 32 bits #define MONE32 ((uint32_t)0xFFFFFFFF) #ifdef HAVE_AVX2 #include #define AVX2LOAD(A) _mm256_load_si256((__m256i*)(A)) #define AVX2LOADU(A) _mm256_loadu_si256((__m256i*)(A)) #define AVX2STORE(res,A) _mm256_store_si256((__m256i*)(res),A); #define AVX2STOREU(res,A) _mm256_storeu_si256((__m256i*)(res),A); #define AVX2SETZERO() _mm256_setzero_si256() #define AVX2SET1_64(A0) _mm256_set1_epi64x(A0) #define AVX2AND_(A,B) _mm256_and_si256(A,B) #define AVX2ADD_64(A,B) _mm256_add_epi64(A,B) #define AVX2MUL(A,B) _mm256_mul_epu32(A,B) #define AVX2SRLI_64(A,i) _mm256_srli_epi64(A,i) #define AVXINNERPROD(res1, mat8, vec8, va, vtmp, prod1, prod2) \ { \ mat8=AVX2LOADU(va); \ vec8=AVX2LOADU(vtmp); \ /* four 32-bits mul, lower parts */ \ /* four 32-bits mul, higher parts */ \ prod1=AVX2MUL(mat8,vec8); \ prod2= AVX2MUL(AVX2SRLI_64(mat8,32),AVX2SRLI_64(vec8,32)); \ res1 = prod1 + prod2; \ va+=8; \ vtmp+=8; \ } \ #define AVXINNERPRODLOOP(res1, mat8, vec8, va, vtmp, prod1, prod2) \ { \ mat8=AVX2LOADU(va); \ vec8=AVX2LOADU(vtmp); \ /* four 32-bits mul, lower parts */ \ /* four 32-bits mul, higher parts */ \ prod1=AVX2MUL(mat8,vec8); \ prod2= AVX2MUL(AVX2SRLI_64(mat8,32),AVX2SRLI_64(vec8,32)); \ res1 += prod1 + prod2; \ va+=8; \ vtmp+=8; \ } \ #endif /* /\* */ /* Barrett reduction */ /* 2^30 < p < 2^31 */ /* r=31 and n=32 */ /* alpha = 2^(n-1) = 2^31, t=n=32, s=r-1=30 */ /* preinv = q = floor( 2^(s+t) / p ) */ /* const uint32_t n, const uint32_t p, */ /* const uint32_t preinv */ static inline uint64_t _MODRED32(const uint64_t n, const uint32_t p, const uint32_t preinv){ /* const uint32_t s = 30; */ /* const uint32_t t = 32; */ /* const uint64_t t1 = n >> s; */ const uint64_t t1 = n >> 30; /* const uint64_t t2 = (t1 * preinv) >> t; */ const uint64_t t2 = (t1 * preinv) >> 32; int64_t r = n - t2 * p; (r >= p) ? r -= p : r; (r >= p) ? r -= p : r; return r; } static inline uint64_t MODRED32(const uint64_t n, const uint32_t p, const uint32_t preinv){ return ((n > ((uint64_t)p)<<31)) ? MODRED32(n-(((uint64_t)p)<<31), p, preinv) : _MODRED32(n, p, preinv); } static inline uint64_t ADDMODRED32(uint64_t a, uint64_t b, const uint32_t p, const uint32_t preinv) { const long neg = p - a; return (neg > b) ? MODRED32((a + b), p, preinv) : MODRED32((b - neg), p, preinv); } static inline uint64_t SUBMODRED32(uint64_t a, uint64_t b, const uint32_t p, const uint32_t preinv) { const long neg = a - b; return (a < b) ? (p + neg) : (neg); } #if HAVE_AVX2 static inline void REDUCE(uint64_t *acc64, uint64_t *acc4x64, __m256i acc_low, __m256i acc_high, const uint32_t fc, const uint32_t preinv, const uint32_t RED_32, const uint32_t RED_64){ AVX2STOREU(acc4x64,acc_low); AVX2STOREU(acc4x64+4,acc_high); /* Reduction */ *acc64=0; acc4x64[0]+=MODRED32((acc4x64[4]>>32)*RED_64,fc,preinv); /* partie basse du registre haut (2^32->2^63) */ acc4x64[0]+=MODRED32((acc4x64[4]&((uint64_t)0xFFFFFFFF))*RED_32,fc,preinv); *acc64+=MODRED32(acc4x64[0],fc,preinv); acc4x64[1]+=MODRED32((acc4x64[5]>>32)*RED_64,fc,preinv); /* partie basse du registre haut (2^32->2^63) */ acc4x64[1]+=MODRED32((acc4x64[5]&((uint64_t)0xFFFFFFFF))*RED_32,fc,preinv); *acc64+=MODRED32(acc4x64[1],fc,preinv); acc4x64[2]+=MODRED32((acc4x64[6]>>32)*RED_64,fc,preinv); /* partie basse du registre haut (2^32->2^63) */ acc4x64[2]+=MODRED32((acc4x64[6]&((uint64_t)0xFFFFFFFF))*RED_32,fc,preinv); *acc64+=MODRED32(acc4x64[2],fc,preinv); acc4x64[3]+=MODRED32((acc4x64[7]>>32)*RED_64, fc, preinv); /* partie basse du registre haut (2^32->2^63) */ acc4x64[3]+=MODRED32((acc4x64[7]&((uint64_t)0xFFFFFFFF))*RED_32,fc,preinv); *acc64+=MODRED32(acc4x64[3],fc,preinv); *acc64=MODRED32(*acc64,fc,preinv); } #endif /* B has l rows, n columns */ /* stores in tmp the entries of B column-wise */ /* tmp = [ B[0][0], B[1][0], ..., B[n][0], B[0][1], ..., B[n][1], ... ] */ static __inline__ void specialize_tmp(uint32_t *tmp, uint32_t ** B, const long l, const long n){ for(long i = 0; i < l; i++){ for(long j = 0; j < n; j++) tmp[j*l + i] = B[i][j]; } } static __inline__ void make_zero(uint32_t ** D, long m, long n){ for(long i = 0; i < m; i++){ for(long j = 0; j < n; j++){ D[i][j] = 0; } } } #ifdef HAVE_AVX2 /* m = number of rows in A l = number of cols in A = number of rows in B n = number of cols in B D = A*B */ void _mod_mat_addmul_transpose_op(uint32_t *D, uint32_t *A, uint32_t *B, const uint32_t m, const uint32_t l, const uint32_t n, const uint32_t fc, const uint32_t preinv, const uint32_t RED_32, const uint32_t RED_64){ __m256i acc_low, acc_high, mask, vec8, mat8; __m256i prod1,prod2; __m256i res1; #if IS_ALIGNED_TMP uint64_t acc4x64[8] ALIGNED32; #else uint64_t acc4x64[8]; #endif uint64_t acc64 = 0; mask=AVX2SET1_64(MONE32); const uint32_t *va; const uint32_t *vtmp; acc_low=AVX2SETZERO(); acc_high=AVX2SETZERO(); //quo(l, 2^6) * 2^6 const uint32_t bl = ((l >> 6) << 6); for(uint32_t i = 0; i < m; i++){ for(uint32_t j = 0; j < n; j++){ acc64 = 0; acc_low=AVX2SETZERO(); acc_high=AVX2SETZERO(); for(uint32_t k = 0; k < bl; k+=64){ /* va = A[i]+k; */ va = A+(i*l)+k; vtmp = B+j*l+k; AVXINNERPROD(res1, mat8, vec8, va, vtmp, prod1, prod2); AVXINNERPRODLOOP(res1, mat8, vec8, va, vtmp, prod1, prod2); AVXINNERPRODLOOP(res1, mat8, vec8, va, vtmp, prod1, prod2); AVXINNERPRODLOOP(res1, mat8, vec8, va, vtmp, prod1, prod2); AVXINNERPRODLOOP(res1, mat8, vec8, va, vtmp, prod1, prod2); AVXINNERPRODLOOP(res1, mat8, vec8, va, vtmp, prod1, prod2); AVXINNERPRODLOOP(res1, mat8, vec8, va, vtmp, prod1, prod2); AVXINNERPRODLOOP(res1, mat8, vec8, va, vtmp, prod1, prod2); acc_low = AVX2ADD_64(acc_low,AVX2AND_(res1,mask)); acc_high = AVX2ADD_64(acc_high,AVX2SRLI_64(res1,32)); } REDUCE(&acc64, acc4x64, acc_low, acc_high, fc, preinv, RED_32, RED_64); uint64_t p = 0, u = 0, d = 0; uint64_t r, Shi = 0, Slo = 0; const long c2 = j*l; const long c1 = i*l; for(uint32_t k = bl; k < l; k++){ /* p = ((uint64_t)A[i][k] * (uint64_t)tmp[c+k]); */ p = ((uint64_t)A[c1+k] * (uint64_t)B[c2+k]); u = p>>32; d = p - (u<<32); Shi += u; Slo += d; } uint64_t hi, lo; hi = Shi>>32; lo = Shi - (hi<<32); r = MODRED32(hi<<32, fc, preinv); r = ADDMODRED32(lo, r, fc, preinv); r = MODRED32((r<<32), fc, preinv); r = ADDMODRED32(Slo, r, fc, preinv); acc64 = ADDMODRED32(acc64, r, fc, preinv); D[i*n+j] = ADDMODRED32(D[i*n+j], acc64, fc, preinv); } } } #endif static inline void sparse_matfglm_mul(CF_t *res, sp_matfglm_t *matxn, CF_t *R, CF_t *tres, const int nc, const mod_t prime, const uint32_t preinv, const uint32_t RED_32, const uint64_t RED_64){ szmat_t ncols = matxn->ncols; szmat_t nrows = matxn->nrows; szmat_t ntriv = ncols - nrows; for(szmat_t j = 0; j < ntriv; j++){ for(int i = 0; i < nc; i++){ uint32_t idx = i*(matxn->ncols); res[idx + matxn->triv_idx[j]] = R[idx + matxn->triv_pos[j]]; } } /* real product */ #ifdef HAVE_AVX2 _mod_mat_addmul_transpose_op(tres, matxn->dense_mat, R, matxn->nrows, matxn->ncols, nc, prime, preinv, RED_32, RED_64); #else fprintf(stderr, "Not implemented yet\n"); exit(1); #endif for(szmat_t j = 0; j < nrows; j++){ for(int i = 0; i < nc; i++){ uint32_t idx = i*(matxn->ncols); res[idx + matxn->dense_idx[j]] = tres[idx + j]; } } } msolve-0.6.5/src/msolve/000077500000000000000000000000001456710632100151305ustar00rootroot00000000000000msolve-0.6.5/src/msolve/Makefile.am000066400000000000000000000024641456710632100171720ustar00rootroot00000000000000lib_LTLIBRARIES = libmsolve.la libmsolve_la_SOURCES = libmsolve.c libmsolve_ladir = $(includedir)/msolve/msolve libmsolve_la_HEADERS = msolve-data.h msolve.h libmsolve_la_CFLAGS = $(SIMD_FLAGS) $(CPUEXT_FLAGS) $(OPENMP_CFLAGS) libmsolve_la_LDFLAGS = -release $(PACKAGE_VERSION) libmsolve_la_LIBADD = ../usolve/libusolve.la ../fglm/libfglm.la ../neogb/libneogb.la EXTRA_DIST = msolve-data.h \ msolve.h \ msolve-data.c \ duplicate.c \ hilbert.c \ linear.c \ lifting.c \ lifting-gb.c \ iofiles.c \ msolve.c \ primes.c \ ../crt/longlong.h \ ../crt/ulong_extras.h \ ../crt/mpq_reconstruct.c \ ../crt/mpz_CRT_ui.c \ ../upolmat/nmod_mat_extra.h \ ../upolmat/nmod_mat_poly_arith.c \ ../upolmat/nmod_mat_poly_mbasis.c \ ../upolmat/nmod_mat_poly_shift.c \ ../upolmat/nmod_poly_mat_utils.c \ ../upolmat/nmod_mat_left_nullspace.c \ ../upolmat/nmod_mat_poly.h \ ../upolmat/nmod_mat_poly_mem.c \ ../upolmat/nmod_poly_mat_pmbasis.c \ ../upolmat/nmod_poly_mat_utils.h \ ../upolmat/nmod_mat_permute_rows.c \ ../upolmat/nmod_mat_poly_io.c \ ../upolmat/nmod_mat_poly_set_from.c \ ../upolmat/nmod_poly_mat_pmbasis.h msolve-0.6.5/src/msolve/duplicate.c000066400000000000000000000320031456710632100172440ustar00rootroot00000000000000 static inline void duplicate_linear_data(int nthreads, int nvars, int nlins, nvars_t **blinvars, uint32_t **blineqs, nvars_t **bsquvars){ for(int i = 1; i < nthreads; i++){ blineqs[i] = calloc(nlins*(nvars + 1), sizeof(uint64_t)); for(long j = 0; j < nlins*(nvars + 1); j++){ blineqs[i][j] = 0; } blinvars[i] = calloc(nvars, sizeof(uint64_t)); for(long j = 0; j < nvars; j++){ blinvars[i][j] = blinvars[0][j]; } bsquvars[i] = calloc(nvars - 1, sizeof(uint64_t)); for(nvars_t j = 0; j < nvars - 1; j++){ bsquvars[i][j] = bsquvars[0][j]; } } } static inline void duplicate_tracer( const int nthreads, const bs_t * const bs, const md_t * const md, trace_t **btrace) { if (btrace[0] != NULL) { for(int i = 1; i < nthreads; i++){ btrace[i] = initialize_trace(bs, md); /* size for trace data */ btrace[i]->std = btrace[0]->std; /* load of trace data */ btrace[i]->ltd = btrace[0]->ltd; /* number of lead monomials of non-redundant elements in Gbasis */ btrace[i]->lml = btrace[0]->lml; /* position of non redundant elements in Gbasis */ btrace[i]->lmps = (bl_t *)calloc((unsigned long)btrace[0]->lml, sizeof(bl_t)); memcpy(btrace[i]->lmps, btrace[0]->lmps, (unsigned long)btrace[0]->lml * sizeof(bl_t)); /* non-redundant lead mon. as short divmask */ btrace[i]->lm = (sdm_t *)calloc((unsigned long)btrace[0]->lml, sizeof(sdm_t)); memcpy(btrace[0]->lm, btrace[i]->lm, (unsigned long)btrace[0]->lml * sizeof(sdm_t)); /* array of trace data per F4 round */ btrace[i]->td = calloc((unsigned long)btrace[0]->ltd, sizeof(td_t)); for(len_t l = 0; l < btrace[0]->ltd; ++l){ btrace[i]->td[l].rld = btrace[0]->td[l].rld; btrace[i]->td[l].tld = btrace[0]->td[l].tld; btrace[i]->td[l].nlm = btrace[0]->td[l].nlm; btrace[i]->td[l].rri = calloc(btrace[0]->td[l].rld, sizeof(len_t)); for(len_t k = 0; k < (btrace[0]->td[l].rld ); ++k){ btrace[i]->td[l].rri[k] = btrace[0]->td[l].rri[k] ; } btrace[i]->td[l].tri = calloc(btrace[0]->td[l].tld, sizeof(len_t)); for(len_t k = 0; k < (btrace[0]->td[l].tld); ++k){ btrace[i]->td[l].tri[k] = btrace[0]->td[l].tri[k] ; } btrace[i]->td[l].nlms = calloc(btrace[0]->td[l].nlm, sizeof(len_t)); for(len_t k = 0; k < (btrace[0]->td[l].nlm); ++k){ btrace[i]->td[l].nlms[k] = btrace[0]->td[l].nlms[k]; } btrace[i]->td[l].rba = (rba_t **)malloc((unsigned long)btrace[0]->td[l].tld * sizeof(rba_t *)); const len_t nrr = btrace[0]->td[l].rld; const unsigned long nlrba = nrr / 2 / 32 + (((nrr / 2) % 32) != 0); for(len_t j = 0; j < (btrace[0]->td[l].tld / 2); ++j) { btrace[i]->td[l].rba[j] = calloc(nlrba, sizeof(rba_t)); } for (len_t j = 0; j < (btrace[0]->td[l].tld / 2); ++j) { for(len_t k = 0; k < nlrba; k++){ btrace[i]->td[l].rba[j][k] = btrace[0]->td[l].rba[j][k]; } } } } } } static inline void duplicate_data_mthread_trace(int nthreads, bs_t *bs, md_t *st, int32_t *num_gb, int32_t **leadmons_ori, int32_t **leadmons_current, /* trace_t **btrace, */ fglm_bms_data_t **bdata_bms, fglm_data_t **bdata_fglm, int32_t **bstart_cf_gb_xn, int32_t **blen_gb_xn, int32_t **bdiv_xn, sp_matfglm_t **bmatrix, param_t **nmod_params, nvars_t nlins, nvars_t *bnlins, nvars_t **blinvars, uint32_t **blineqs, nvars_t **bsquvars){ const long len_xn = bmatrix[0]->nrows; const long dquot = bmatrix[0]->ncols; const long len = num_gb[0] * (st->nvars); for(int i = 0; i lml */); for(long j = 0; j < len_xn; j++){ bstart_cf_gb_xn[i][j] = bstart_cf_gb_xn[0][j]; blen_gb_xn[i][j] = blen_gb_xn[0][j]; } for(long j = 0; j < num_gb[0]; j++){ bdiv_xn[i][j] = bdiv_xn[0][j]; } } for(int i=1; i < nthreads; i++){ num_gb[i] = num_gb[0]; } /* need to duplicate bmatrix */ for(int i = 1; i < nthreads; i++){ bmatrix[i] = calloc(1, sizeof(sp_matfglm_t)); bmatrix[i]->ncols = dquot; bmatrix[i]->nrows = len_xn; long len1 = dquot * len_xn; long len2 = dquot - len_xn; sp_matfglm_t *matrix = bmatrix[i]; if(posix_memalign((void **)&matrix->dense_mat, 32, sizeof(CF_t)*len1)){ fprintf(stderr, "Problem when allocating matrix->dense_mat\n"); exit(1); } else{ for(long j = 0; j < len1; j++){ matrix->dense_mat[j] = 0; } } if(posix_memalign((void **)&matrix->triv_idx, 32, sizeof(CF_t)*(dquot - len_xn))){ fprintf(stderr, "Problem when allocating matrix->triv_idx\n"); exit(1); } else{ for(long j = 0; j < (dquot-len_xn); j++){ matrix->triv_idx[j] = 0; } } if(posix_memalign((void **)&matrix->triv_pos, 32, sizeof(CF_t)*len2)){ fprintf(stderr, "Problem when allocating matrix->triv_pos\n"); exit(1); } else{ for(long j = 0; j < len2; j++){ matrix->triv_pos[j] = 0; } } if(posix_memalign((void **)&matrix->dense_idx, 32, sizeof(CF_t)*len_xn)){ fprintf(stderr, "Problem when allocating matrix->dense_idx\n"); exit(1); } else{ for(long j = 0; j < len_xn; j++){ matrix->dense_idx[j] = 0; } } if(posix_memalign((void **)&matrix->dst, 32, sizeof(CF_t)*len_xn)){ fprintf(stderr, "Problem when allocating matrix->dense_idx\n"); exit(1); } else{ for(long j = 0; j < len_xn; j++){ matrix->dst[j] = 0; } } } for(int i = 1; i < nthreads; i++){ bdata_fglm[i] = allocate_fglm_data(len_xn, dquot, (st->nvars)); bdata_bms[i] = allocate_fglm_bms_data(dquot, 65521); nmod_params[i] = allocate_fglm_param(nmod_params[0]->charac, (st->nvars)); nmod_poly_set(nmod_params[i]->elim, nmod_params[0]->elim); nmod_poly_set(nmod_params[i]->denom, nmod_params[0]->denom); for(long j = 0; j < (st->nvars) - 2; j++){ nmod_poly_set(nmod_params[i]->coords[j], nmod_params[0]->coords[j]); } } /* duplicate_tracer(nthreads, bs, st, btrace); */ duplicate_linear_data(nthreads, st->nvars, nlins, blinvars, blineqs, bsquvars); } static inline void duplicate_data_mthread(int nthreads, nvars_t nv, int32_t *num_gb, int32_t **leadmons_ori, int32_t **leadmons_current, fglm_bms_data_t **bdata_bms, fglm_data_t **bdata_fglm, int32_t **bstart_cf_gb_xn, int32_t **blen_gb_xn, int32_t **bdiv_xn, sp_matfglm_t **bmatrix, param_t **nmod_params){ const long len_xn = bmatrix[0]->nrows; const long dquot = bmatrix[0]->ncols; const long len = num_gb[0] * nv; for(int i = 0; i < nthreads; i++){ leadmons_current[i] = (int32_t *)calloc(len, sizeof(int32_t)); } /* leadmons_ori[0] has already been allocated*/ for(int i = 1; i < nthreads; i++){ leadmons_ori[i] = (int32_t *)calloc(len, sizeof(int32_t)); for(long j = 0; j < len; j++){ leadmons_ori[i][j] = leadmons_ori[0][j]; } } for(long i = 1; i < nthreads; i++){ bstart_cf_gb_xn[i] = malloc(sizeof(int32_t) * len_xn); blen_gb_xn[i] = malloc(sizeof(int32_t) * len_xn); bdiv_xn[i] = malloc(sizeof(int32_t) * num_gb[0]/* bs->lml */); for(long j = 0; j < len_xn; j++){ bstart_cf_gb_xn[i][j] = bstart_cf_gb_xn[0][j]; blen_gb_xn[i][j] = blen_gb_xn[0][j]; } for(long j = 0; j < num_gb[0]; j++){ bdiv_xn[i][j] = bdiv_xn[0][j]; } } for(int i=1; i < nthreads; i++){ num_gb[i] = num_gb[0]; } /* need to duplicate bmatrix */ for(int i = 1; i < nthreads; i++){ bmatrix[i] = calloc(1, sizeof(sp_matfglm_t)); bmatrix[i]->ncols = dquot; bmatrix[i]->nrows = len_xn; long len1 = dquot * len_xn; long len2 = dquot - len_xn; sp_matfglm_t *matrix = bmatrix[i]; if(posix_memalign((void **)&matrix->dense_mat, 32, sizeof(CF_t)*len1)){ fprintf(stderr, "Problem when allocating matrix->dense_mat\n"); exit(1); } else{ for(long j = 0; j < len1; j++){ matrix->dense_mat[j] = 0; } } if(posix_memalign((void **)&matrix->triv_idx, 32, sizeof(CF_t)*(dquot - len_xn))){ fprintf(stderr, "Problem when allocating matrix->triv_idx\n"); exit(1); } else{ for(long j = 0; j < (dquot-len_xn); j++){ matrix->triv_idx[j] = 0; } } if(posix_memalign((void **)&matrix->triv_pos, 32, sizeof(CF_t)*len2)){ fprintf(stderr, "Problem when allocating matrix->triv_pos\n"); exit(1); } else{ for(long j = 0; j < len2; j++){ matrix->triv_pos[j] = 0; } } if(posix_memalign((void **)&matrix->dense_idx, 32, sizeof(CF_t)*len_xn)){ fprintf(stderr, "Problem when allocating matrix->dense_idx\n"); exit(1); } else{ for(long j = 0; j < len_xn; j++){ matrix->dense_idx[j] = 0; } } if(posix_memalign((void **)&matrix->dst, 32, sizeof(CF_t)*len_xn)){ fprintf(stderr, "Problem when allocating matrix->dense_idx\n"); exit(1); } else{ for(long j = 0; j < len_xn; j++){ matrix->dst[j] = 0; } } } for(int i = 1; i < nthreads; i++){ bdata_fglm[i] = allocate_fglm_data(len_xn, dquot, nv); bdata_bms[i] = allocate_fglm_bms_data(dquot, 65521); nmod_params[i] = allocate_fglm_param(nmod_params[0]->charac, nv); nmod_poly_set(nmod_params[i]->elim, nmod_params[0]->elim); nmod_poly_set(nmod_params[i]->denom, nmod_params[0]->denom); for(long j = 0; j < nv - 2; j++){ nmod_poly_set(nmod_params[i]->coords[j], nmod_params[0]->coords[j]); } } if(nthreads > 1){ fprintf(stderr, "Duplication of data to be implemented\n"); exit(1); } } static inline void duplicate_data_mthread_gbtrace(int nthreads, bs_t *bs, md_t *st, int32_t *num_gb, int32_t **leadmons_ori, int32_t **leadmons_current, trace_t **btrace){ const len_t len = num_gb[0] * (st->nvars); for(int i = 0; i < nthreads; i++){ leadmons_current[i] = (int32_t *)calloc(len, sizeof(int32_t)); } /* leadmons_ori[0] has already been allocated*/ for(int i = 1; i < nthreads; i++){ leadmons_ori[i] = (int32_t *)calloc(len, sizeof(int32_t)); for(len_t j = 0; j < len; j++){ leadmons_ori[i][j] = leadmons_ori[0][j]; } } for(int i=1; i < nthreads; i++){ num_gb[i] = num_gb[0]; } duplicate_tracer(nthreads, bs, st, btrace); } msolve-0.6.5/src/msolve/hilbert.c000066400000000000000000002646101456710632100167360ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "../fglm/data_fglm.c" #include "../fglm/libfglm.h" #define REDUCTION_ALLINONE 1 static void (*copy_poly_in_matrix_from_bs)(sp_matfglm_t* matrix, long nrows, bs_t *bs, ht_t *ht, long idx, long len, long start, long pos, int32_t *lmb, const int nv, const long fc); static int is_pure_power(const int32_t *bexp, const int nv){ int cnt = 0; for(int i = 0; i < nv; i++){ if(bexp[i]==0){ cnt++; } } if(cnt>=nv-1){ return 1; } return 0; } static int32_t *get_lead_monomials(const int32_t *bld, int32_t **blen, int32_t **bexp, data_gens_ff_t *gens){ long ngens = bld[0]; long nvars = gens->nvars; int32_t *bexp_lm = malloc(sizeof(int32_t)*ngens*nvars); long npos = 0; for(long i = 0; i < ngens; i++){ for(long k = 0; k < nvars; k++){ (bexp_lm)[i*nvars + k] = (*bexp)[npos*nvars + k]; } npos+=(*blen)[i]; } return bexp_lm; } static inline int has_dimension_zero(const long length, const int nv, int32_t *bexp_lm){ long ppwr = 0; for(long i = 0; i < length; i++){ int boo = is_pure_power(bexp_lm + i*nv, nv); if(boo){ ppwr++; } if(ppwr >= nv){ return 1; } } if(ppwr >= nv){ return 1; } return 0; } static inline int is_divisible_exp(long nvars, int32_t *exp1, int32_t *exp2){ for(long i = 0; i < nvars; i++){ if(exp2[i]>exp1[i]){ return 0; } } return 1; } static inline int is_divisible_lexp(long nvars, long length, int32_t *exp1, int32_t *bexp){ for(long i = 0; i < length; i++){ if(is_divisible_exp(nvars, exp1, (bexp+i*nvars))){ return 1; } } return 0; } static inline int is_divisible_exp_elim(int32_t nvars, int32_t nev, int32_t *exp1, int32_t *exp2){ for(int32_t i = nev; i < nvars; i++){ if(exp2[i]>exp1[i]){ return 0; } } return 1; } static inline int is_divisible_lexp_elim(int32_t nvars, int32_t nev, long length, int32_t *exp1, int32_t *bexp){ for(long i = 0; i < length; i++){ if(is_divisible_exp_elim(nvars, nev, exp1, (bexp+i*nvars))){ return 1; } } return 0; } static inline int is_divisible_lexp_without_last_variable(long nvars, long length, int32_t *exp1, int32_t *bexp){ for(long i = 0; i < length; i++){ if(is_divisible_exp(nvars-1, exp1, (bexp+i*nvars))){ return 1; } } return 0; } /*ind is an array of long of length length adds entries of ind */ static inline int32_t sum(int32_t *ind, int32_t length){ int32_t s= 0; for(int32_t i = 0; i < length; i++){ s += ind[i]; } return s; } /* - len1 is the current dimension of the quotient - len_lm is the number of polynomials in the GB - basis will contain the final monomial basis - new_basis */ static inline int32_t generate_new_elts_basis(int32_t nvars, int32_t *ind, len_t len1, int32_t *basis, int32_t *new_basis, len_t len_lm, int32_t *bexp_lm){ len_t c = 0; len_t def = 0; for(int64_t n = nvars-1; n >= 0; n--){ for(len_t i = ind[nvars-1-n]; i < len1; i++){ for(int64_t k = 0; k < nvars; k++){ new_basis[c*nvars+k] = basis[i*nvars+k]; } new_basis[c*nvars+n]++; if(!is_divisible_lexp(nvars, len_lm, (new_basis+c*nvars), bexp_lm)){ c++; } else{ def++; } } } return c; } /* takes as input an exponent and an index and returns the degree of the variable next to the index */ static inline int degree_prev_var(int32_t *exp, long n){ return(exp[n+1]); } static inline void update_indices(int32_t *ind, int32_t *basis, long dquot, long new_length, long nvars){ ind[0] = dquot; for(long n = nvars - 2; n >= 0 ; n--){ for(long i = ind[nvars-1-n-1]; i < dquot + new_length; i++){ if(degree_prev_var(basis+i*nvars, n)==0){ ind[nvars-n-1] = i; break; } for(long k = n; k>=0; k--){ ind[nvars-k-1] = dquot + new_length; } } } } /** length is the length of the GB nvars is the number of variables bexp_lm encodes the leading monomials dquot is a pointer to an integer that will be the dimension of the quotient assumes bexp_lm is for grevlex ordering */ static inline int32_t *monomial_basis(long length, long nvars, int32_t *bexp_lm, long *dquot){ /* basis will contain the monomial basis */ int32_t *basis = calloc(nvars, sizeof(int32_t)); (*dquot) = 0; if(is_divisible_lexp(nvars, length, (basis), bexp_lm)){ free(basis); return NULL; } else{ (*dquot)++; } int32_t *ind = calloc(nvars, sizeof(int32_t)); #ifdef DEBUGHILBERT fprintf(stderr, "new = %ld \n", sum(ind, nvars) + nvars); #endif int32_t *new_basis = malloc(sizeof(int32_t) * nvars * (sum(ind, nvars) + nvars)); int32_t new_length = generate_new_elts_basis(nvars, ind, (*dquot), basis, new_basis, length, bexp_lm); #ifdef DEBUGHILBERT // display_monomials_from_array(stderr, new_length, new_basis, gens); fprintf(stderr, "%ld new elements.\n", new_length); #endif while(new_length>0){ int32_t *basis2 = realloc(basis, ((*dquot) + new_length) * nvars * sizeof(int32_t *)); if(basis2==NULL){ fprintf(stderr, "Issue with realloc\n"); exit(1); } basis = basis2; for(long i = 0; i < new_length; i++){ for(long k = 0; k < nvars; k++){ (basis)[((*dquot) + i)*nvars+k] = (new_basis)[i*nvars+k]; } } update_indices(ind, basis, *dquot, new_length, nvars); (*dquot) += new_length; #ifdef DEBUGHILBERT fprintf(stderr, "Update indices\n"); for(long i = 0; i < nvars; i++) fprintf(stderr, "%ld ", ind[i]); fprintf(stderr, "\n"); fprintf(stderr, "new = %ld \n", sum(ind, nvars) + nvars); #endif int32_t *new_basis2 = realloc(new_basis, sizeof(int32_t) * nvars * (sum(ind, nvars) + nvars)); if(new_basis==NULL){ fprintf(stderr, "Issue with realloc\n"); exit(1); } new_basis=new_basis2; new_length = generate_new_elts_basis(nvars, ind, (*dquot), basis, new_basis, length, bexp_lm); #ifdef DEBUGHILBERT fprintf(stderr, "%ld new elements.\n", new_length); #endif } free(new_basis); free(ind); return basis; } /** nvars is the number of variables sht is a secondary htable of the monomials dquot is a integer representing the dimension of the subspace */ static inline int32_t *monomial_basis_colon(long length, long nvars, int32_t *bexp_lm, long *dquot, const long maxdeg){ int32_t *basis = calloc(nvars, sizeof(int32_t)); (*dquot) = 0; if(is_divisible_lexp(nvars, length, (basis), bexp_lm)){ fprintf(stderr, "Stop\n"); free(basis); return NULL; } else{ (*dquot)++; } int32_t *ind = calloc(nvars, sizeof(int32_t)); #ifdef DEBUGHILBERT fprintf(stderr, "new = %ld \n", sum(ind, nvars) + nvars); #endif int32_t *new_basis = malloc(sizeof(int32_t) * nvars * (sum(ind, nvars) + nvars)); long new_length = generate_new_elts_basis(nvars, ind, (*dquot), basis, new_basis, length, bexp_lm); #ifdef DEBUGHILBERT display_monomials_from_array(stderr, new_length, new_basis, gens); fprintf(stderr, "%ld new elements.\n", new_length); #endif long deg = 1; while(new_length>0 && deg <= maxdeg){ int32_t *basis2 = realloc(basis, ((*dquot) + new_length) * nvars * sizeof(int32_t *)); if(basis2==NULL){ fprintf(stderr, "Issue with realloc\n"); exit(1); } basis = basis2; for(long i = 0; i < new_length; i++){ for(long k = 0; k < nvars; k++){ (basis)[((*dquot) + i)*nvars+k] = (new_basis)[i*nvars+k]; } } update_indices(ind, basis, *dquot, new_length, nvars); (*dquot) += new_length; #ifdef DEBUGHILBERT fprintf(stderr, "Update indices\n"); for(long i = 0; i < nvars; i++) fprintf(stderr, "%ld ", ind[i]); fprintf(stderr, "\n"); fprintf(stderr, "new = %ld \n", sum(ind, nvars) + nvars); #endif int32_t *new_basis2 = realloc(new_basis, sizeof(int32_t) * nvars * (sum(ind, nvars) + nvars)); if(new_basis==NULL){ fprintf(stderr, "Issue with realloc\n"); exit(1); } new_basis=new_basis2; new_length = generate_new_elts_basis(nvars, ind, (*dquot), basis, new_basis, length, bexp_lm); #ifdef DEBUGHILBERT fprintf(stderr, "%ld new elements.\n", new_length); #endif deg++; } free(new_basis); free(ind); return basis; } /** nvars is the number of variables sht is a secondary htable of the monomials dquot is a integer representing the dimension of the subspace */ static inline int32_t *monomial_basis_colon_no_zero(long length, long nvars, int32_t *bexp_lm, long *dquot, const long maxdeg){ int32_t *basis = calloc(nvars, sizeof(int32_t)); (*dquot) = 0; if(is_divisible_lexp(nvars, length, (basis), bexp_lm)){ fprintf(stderr, "Stop\n"); free(basis); return NULL; } else{ (*dquot)++; } int32_t *ind = calloc(nvars, sizeof(int32_t)); #ifdef DEBUGHILBERT fprintf(stderr, "new = %ld \n", sum(ind, nvars) + nvars); #endif int32_t *new_basis = malloc(sizeof(int32_t) * nvars * (sum(ind, nvars) + nvars)); long new_length = generate_new_elts_basis(nvars, ind, (*dquot), basis, new_basis, length, bexp_lm); #ifdef DEBUGHILBERT display_monomials_from_array(stderr, new_length, new_basis, gens); fprintf(stderr, "%ld new elements.\n", new_length); #endif long deg = 1; while(new_length>0 && deg <= maxdeg){ int32_t *basis2 = realloc(basis, ((*dquot) + new_length) * nvars * sizeof(int32_t *)); if(basis2==NULL){ fprintf(stderr, "Issue with realloc\n"); exit(1); } basis = basis2; for(long i = 0; i < new_length; i++){ for(long k = 0; k < nvars; k++){ (basis)[((*dquot) + i)*nvars+k] = (new_basis)[i*nvars+k]; } } update_indices(ind, basis, *dquot, new_length, nvars); (*dquot) += new_length; #ifdef DEBUGHILBERT fprintf(stderr, "Update indices\n"); for(long i = 0; i < nvars; i++) fprintf(stderr, "%ld ", ind[i]); fprintf(stderr, "\n"); fprintf(stderr, "new = %ld \n", sum(ind, nvars) + nvars); #endif int32_t *new_basis2 = realloc(new_basis, sizeof(int32_t) * nvars * (sum(ind, nvars) + nvars)); if(new_basis==NULL){ fprintf(stderr, "Issue with realloc\n"); exit(1); } new_basis=new_basis2; new_length = generate_new_elts_basis(nvars, ind, (*dquot), basis, new_basis, length, bexp_lm); #ifdef DEBUGHILBERT fprintf(stderr, "%ld new elements.\n", new_length); #endif deg++; } free(new_basis); free(ind); /* cleanup by removing monomials that will be sent to 0 after iterative multiplication by xn */ long new_dquot=0; for (long i = 0; i < *dquot; i++) { if (is_divisible_lexp_without_last_variable(nvars,length, (basis+i*nvars),bexp_lm)) { /* keep this monomial */ for (long k = 0; k < nvars; k++) { basis[new_dquot*nvars+k]= basis[i*nvars+k]; } new_dquot++; } } if (new_dquot == 0) { fprintf(stderr, "Vector space is too small\n"); exit(1); } *dquot= new_dquot; basis= realloc (basis, new_dquot * nvars * sizeof(int32_t)); return basis; } static inline long get_div_xn(int32_t *bexp_lm, long length, long nvars, int32_t *div_xn){ long l = 0; for(long i = 0; i < length; i++){ if(bexp_lm[i*nvars + (nvars-1)]!=0){ div_xn[l] = i; l++; } } return l; } static inline long get_div_xn_bounded(int32_t *bexp_lm, long length, long nvars, int32_t *div_xn, int32_t *div_not_xn, long* l_not, const long maxdeg){ long l = 0; *l_not = 0; for(long i = 0; i < length; i++){ long deg = 0; for (long j = 0; j < nvars; j++) { deg += bexp_lm[i*nvars+j]; } if (deg <= maxdeg) { if (bexp_lm[i*nvars + (nvars-1)]!=0){ div_xn[l] = i; l++; }else{ div_not_xn[*l_not] = i; (*l_not)++; } } } return l; } /* One of the exp. encoded is hashed */ static inline int is_equal_exponent_dm(bs_t *bs, ht_t *ht, long idx, long pos, int32_t *exp2, const long nv){ const bl_t bi = bs->lmps[idx]; hm_t *dt = bs->hm[bi] + OFFSET; for(long k = 0; k < nv-1 ; k++){ /* in hash table exponent vectors store their degree in the first entry, * thus we have to go by "k+1" */ int e = (int32_t)ht->ev[dt[pos]][k+1]; if(e != exp2[k]){ return 0; } } int e = (int32_t)ht->ev[dt[pos]][nv]; return (e == exp2[nv - 1]); } static inline int is_equal_exponent(int32_t *exp1, int32_t *exp2, const long nvars){ for(long i = 0; i < nvars - 1; i++){ if(exp1[i]!=exp2[i]){ return 0; } } return ((exp1[nvars-1]) == exp2[nvars-1]); } static inline int is_equal_exponent_elim(int32_t *exp1, int32_t *exp2, const long nvars, const long elim){ for(long i = 0; i < nvars - elim - 1; i++){ if(exp1[i + elim]!=exp2[i]){ return 0; } } return ((exp1[nvars-1]) == exp2[nvars - elim -1]); } static inline int is_equal_exponent_bs(const ht_t * const exp1, int32_t hmj, int32_t *evi, int32_t *exp2, const long nvars){ /* printf ("\n"); */ for(long i = 0; i < nvars - 1; i++){ /* printf ("exp1[%ld]=%d\texp2[%ld]=%d\n",i,exp1->ev[hmj][evi[i]],i,exp2[i]); */ if(exp1->ev[hmj][evi[i]]!=exp2[i]){ return 0; } } /* printf ("exp1[%ld]=%d\texp2[%ld]=%d\n",nvars-1,exp1->ev[hmj][evi[nvars-1]], */ /* nvars-1,exp2[nvars-1]); */ return ((exp1->ev[hmj][evi[nvars-1]]) == exp2[nvars-1]); } /* returns -1 if exp1 is smaller * return 0 if they are the same * returns 1 if exp1 is larger */ static inline int is_larger_exponent(int32_t *exp1, int32_t *exp2, const long nvars){ int32_t deg1 = 0; int32_t deg2 = 0; for(long i = 0; i < nvars; i++){ deg1 += exp1[i]; deg2 += exp2[i]; } /* printf ("deg1= %d, deg2=%d\n",deg1,deg2); */ if (deg1 < deg2){ return -1; } if (deg1 > deg2){ return 1; } for (long i = nvars-1; i>1; i--) { /* printf ("x[%ld]: %d, %d\n",i,exp1[i],exp2[i]); */ if(exp1[i]exp2[i]){ return -1; } } return 0; } /* returns -1 if exp1 is smaller * return 0 if they are the same * returns 1 if exp1 is larger */ static inline int is_larger_exponent_bs(const ht_t * const exp1, int32_t hmj, int32_t *evi, int32_t *exp2, const long nvars){ int32_t deg1 = 0; int32_t deg2 = 0; for(long i = 0; i < nvars; i++){ deg1 += exp1->ev[hmj][evi[i]]; deg2 += exp2[i]; } /* printf ("deg1= %d, deg2=%d\n",deg1,deg2); */ if (deg1 < deg2){ return -1; } if (deg1 > deg2){ return 1; } for (long i = nvars-1; i>1; i--) { /* printf ("x[%ld]: %d, %d\n",i,exp1->ev[hmj][evi[i]],exp2[i]); */ if(exp1->ev[hmj][evi[i]]ev[hmj][evi[i]]>exp2[i]){ return -1; } } return 0; } static inline int is_equal_exponent_xxn(int32_t *exp1, int32_t *exp2, const long nvars){ for(long i = 0; i < nvars - 1; i++){ if(exp1[i]!=exp2[i]){ return 0; } } return ((exp1[nvars-1]+1) == exp2[nvars-1]); } static inline int is_divisible_exponent_xxn(int32_t *exp1, int32_t *exp2, const long nvars){ for(long i = 0; i < nvars - 1; i++){ if(exp1[i]= exp2[nvars-1]); } static inline int member_xxn(int32_t *exp, int32_t *bexp_lm, int len, long *pos, const int nv){ for(long i=1; i < len; i++){ if(is_equal_exponent_xxn(exp, bexp_lm + (i*nv), nv)){ *pos = i; return 1; } } return 0; } static inline void copy_poly_in_matrix_old(data_gens_ff_t *gens, sp_matfglm_t* matrix, long nrows, int32_t *bcf, int32_t **bexp, int32_t **blen, long start, long pos, int32_t *lmb){ int32_t j; int32_t end = start + pos;//(*blen)[pos]; fprintf(stderr, "copy_poly\n"); /* fprintf(stderr, "\nstart = %ld, end = %ld\n", start, end); */ /* for(j = start; j < end; j++){ */ /* display_term(stderr, j, gens, blen, bcf, bexp); */ /* if(j < end - 1){ */ /* // if(j < (*blen)[pos] - 1){ */ /* fprintf(stderr, "+"); */ /* } */ /* } */ long N = nrows * (matrix->ncols) - (start + 1); if((end-start) == matrix->ncols + 1){ for(j = start + 1; j < end; j++){ matrix->dense_mat[N + j] = gens->field_char - bcf[(end + start) - j]; } } else{ long i; fprintf(stderr, "\n"); fprintf(stderr, "\n"); display_monomial_full(stderr, gens->nvars, NULL, 0, (*bexp) + (start+1)*gens->nvars); fprintf(stderr, ", "); display_monomial_full(stderr, gens->nvars, NULL, 0, lmb + ((end-start-2))*gens->nvars); fprintf(stderr, ", "); display_monomial_full(stderr, gens->nvars, NULL, 0, lmb + ((end-start-1))*gens->nvars); fprintf(stderr, ", "); display_monomial_full(stderr, gens->nvars, NULL, 0, lmb + ((end-start-3))*gens->nvars); fprintf(stderr, "\n"); fprintf(stderr, "\n"); for(i=(matrix->ncols)-1; i >= 0; i--){ display_monomial_full(stderr, gens->nvars, NULL, 0, (*bexp) + (start+1)*gens->nvars);fprintf(stderr, ", "); display_monomial_full(stderr, gens->nvars, NULL, 0, lmb + (i*gens->nvars)); fprintf(stderr, "\n"); if(is_equal_exponent((*bexp) + (start+1)*gens->nvars, lmb+(i*gens->nvars), gens->nvars)) break; } if(i+1 == end - start - 1){ for(j = start + 1; j < end; j++){ matrix->dense_mat[N + j] = gens->field_char - bcf[(end + start) - j]; } } else{ fprintf(stderr, "Some coefficients are null\n"); fprintf(stderr, "i + 1 = %ld\n", i + 1); fprintf(stderr, "end - start - 1 = %ld\n", end - start - 1); exit(1); } } } /** copy of the pol whose coeffs are indexed between start and start + pos **/ static inline void copy_poly_in_matrix(sp_matfglm_t* matrix, long nrows, int32_t *bcf, int32_t **bexp, int32_t **blen, long start, long pos, int32_t *lmb, const int nv, const long fc){ int32_t j; long end = start + pos;//(*blen)[pos]; #if DEBUGBUILDMATRIX > 1 fprintf(stderr, "\nstart = %ld, end = %ld\n", start, end); for(j = start; j < end; j++){ // display_term(stderr, j, gens, blen, bcf, bexp); if(j < end - 1){ // if(j < (*blen)[pos] - 1){ fprintf(stderr, "+"); } } fprintf(stderr, "\n"); #endif long N = nrows * (matrix->ncols) - (start + 1); if((end-start) == matrix->ncols + 1){ for(j = start + 1; j < end; j++){ matrix->dense_mat[N + j] = fc - bcf[(end + start) - j]; } } else{ if(is_equal_exponent((*bexp) + (start+1)*nv, lmb+((end-start-2)*nv), nv)){ for(j = start + 1; j < end; j++){ matrix->dense_mat[N + j] = fc - bcf[(end + start) - j]; } } else{ long i; long N = nrows * matrix->ncols ; long k = 0; for(i = 0; i < matrix->ncols; i++){ if(is_equal_exponent((*bexp) + (end - 1 - k) * nv, lmb + i * nv, nv)){ matrix->dense_mat[N + i] = fc - bcf[end - 1 - k]; k++; } } } } } static inline void copy_poly_in_matrixcol(sp_matfglmcol_t* matrix, long nrows, int32_t *bcf, int32_t **bexp, int32_t **blen, long start, long pos, int32_t *lmb, const int nv, const long fc){ int32_t j; long end = start + pos;//(*blen)[pos]; #if DEBUGBUILDMATRIX > 0 fprintf(stderr, "\nstart = %ld, end = %ld\n", start, end); for(j = start; j < end; j++){ // display_term(stderr, j, gens, blen, bcf, bexp); if(j < end - 1){ // if(j < (*blen)[pos] - 1){ fprintf(stderr, "+"); } } fprintf(stderr, "\n"); #endif long N = nrows * (matrix->ncols) - (start + 1); if((end-start) == matrix->ncols + 1){ for(j = start + 1; j < end; j++){ matrix->dense_mat[N + j] = fc - bcf[(end + start) - j]; } } else{ if(is_equal_exponent((*bexp) + (start+1)*nv, lmb+((end-start-2)*nv), nv)){ for(j = start + 1; j < end; j++){ matrix->dense_mat[N + j] = fc - bcf[(end + start) - j]; } } else{ long i; long N = nrows * matrix->ncols ; long k = 0; for(i = 0; i < matrix->ncols; i++){ if(is_equal_exponent((*bexp) + (end - 1 - k) * nv, lmb + i * nv, nv)){ matrix->dense_mat[N + i] = fc - bcf[end - 1 - k]; k++; } } } } } static inline void copy_poly_in_matrixcol_no_zero(sp_matfglmcol_t* matrix, long nrows, int32_t *bcf, int32_t **bexp, int32_t **blen, long start, long pos, int32_t *lmb, const int nv, const long fc){ long end = start + pos;//(*blen)[pos]; #if DEBUGBUILDMATRIX > 0 int32_t j; fprintf(stderr, "\nstart = %ld, end = %ld\n", start, end); for(j = start; j < end; j++){ // display_term(stderr, j, gens, blen, bcf, bexp); if(j < end - 1){ // if(j < (*blen)[pos] - 1){ fprintf(stderr, "+"); } } fprintf(stderr, "\n"); #endif long i; long N = nrows * matrix->ncols ; long k = 0; /* printf("["); */ for(i = 0; i < matrix->ncols; i++){ if (k < end) { int b = is_larger_exponent((*bexp) + (end - 1 - k) * nv, lmb + i * nv, nv); while (b < 0 && k < end-2) { k++; b = is_larger_exponent((*bexp) + (end - 1 - k) * nv, lmb + i * nv, nv); } if(!b){ /* equal exponent */ matrix->dense_mat[N + i] = fc - bcf[end - 1 - k]; /* printf("%u, ",matrix->dense_mat[N + i]); */ k++; } } } /* printf("]\n"); */ } static inline void copy_extrapoly_in_vector(uint32_t* vector, long ncols, int32_t *lmb, len_t pos, const bs_t * const tbr, const ht_t * const bht, int32_t* evi, const md_t *st, const int nv, const long maxdeg){ len_t idx = tbr->lmps[pos]; /* printf ("idx=%d\n",idx); */ /* if (tbr->hm[idx] == NULL) {*/ len_t * hm = tbr->hm[idx]+OFFSET; len_t len = tbr->hm[idx][LENGTH]; /* printf ("len=%d\n",len); */ long i; long k = 0; /* to remove monomials outside the vector space, we just look at the * leading ones */ uint32_t deglm = 0; for (long j = 0; j < nv; j++) { deglm += lmb[k*nv + j]; } while (deglm > maxdeg) { k++; deglm = 0; for (long j = 0; j < nv; j++) { deglm += lmb[k*nv + j]; } } /* printf ("starts at k=%ld with coeff %d\n",k,tbr->cf_32[tbr->hm[idx][COEFFS]][k]); */ /* printf ("ends at k=%ld with coeff %d\n",len-1-k, */ /* tbr->cf_32[tbr->hm[idx][COEFFS]][len-1-k]); */ /* printf ("["); */ for(i = 0; i < ncols; i++){ if(is_equal_exponent_bs(bht,hm[len-1-k],evi,lmb + i * nv,nv)){ vector[i] = tbr->cf_32[tbr->hm[idx][COEFFS]][len-1-k]; /* printf ("%u, ",vector[i]); */ k++; } } /* printf("]\n"); */ } static inline void copy_extrapoly_in_vector_no_zero(uint32_t* vector, long ncols, int32_t *lmb, len_t pos, const bs_t * const tbr, const ht_t * const bht, int32_t* evi, const md_t *st, const int nv, const long maxdeg){ len_t idx = tbr->lmps[pos]; /* printf ("idx=%d\n",idx); */ /* if (tbr->hm[idx] == NULL) {*/ len_t * hm = tbr->hm[idx]+OFFSET; len_t len = tbr->hm[idx][LENGTH]; /* printf ("len=%d\n",len); */ long i; long k = 0; /* printf ("["); */ for(i = 0; i < ncols; i++){ if (k < len) { int b = is_larger_exponent_bs(bht,hm[len-1-k],evi,lmb + i * nv,nv); while (b < 0 && k < len-2) { k++; b = is_larger_exponent_bs(bht,hm[len-1-k],evi,lmb + i * nv,nv); } if(!b){ /* equal_exponent */ vector[i] = tbr->cf_32[tbr->hm[idx][COEFFS]][len-1-k]; /* printf ("%u, ",vector[i]); */ k++; } } } /* printf("]\n"); */ } static inline void copy_extrapoly_in_matrixcol(sp_matfglmcol_t* matrix, long nrows, int32_t *lmb, len_t pos, const bs_t * const tbr, const ht_t * const bht, int32_t* evi, const md_t *st, const int nv, const long maxdeg){ len_t idx = tbr->lmps[pos]; /* printf ("idx=%d\n",idx); */ /* if (tbr->hm[idx] == NULL) {*/ len_t * hm = tbr->hm[idx]+OFFSET; len_t len = tbr->hm[idx][LENGTH]; /* printf ("len=%d\n",len); */ long i; long N = nrows * matrix->ncols ; long k = 0; /* to remove monomials outside the vector space, we just look at the * leading ones */ uint32_t deglm = 0; for (long j = 0; j < nv; j++) { deglm += lmb[k*nv + j]; } while (deglm > maxdeg) { k++; deglm = 0; for (long j = 0; j < nv; j++) { deglm += lmb[k*nv + j]; } } /* printf ("starts at k=%ld with coeff %d\n",k,tbr->cf_32[tbr->hm[idx][COEFFS]][k]); */ /* printf ("ends at k=%ld with coeff %d\n",len-1-k, */ /* tbr->cf_32[tbr->hm[idx][COEFFS]][len-1-k]); */ /* printf ("["); */ for(i = 0; i < matrix->ncols; i++){ if(is_equal_exponent_bs(bht,hm[len-1-k],evi,lmb + i * nv,nv)){ matrix->dense_mat[N + i] = tbr->cf_32[tbr->hm[idx][COEFFS]][len-1-k]; /* printf ("%u, ",matrix->dense_mat[N+i]); */ k++; } } /* printf("]\n"); */ } static inline void copy_extrapoly_in_matrixcol_no_zero(sp_matfglmcol_t* matrix, long nrows, int32_t *lmb, len_t pos, const bs_t * const tbr, const ht_t * const bht, int32_t* evi, const md_t *st, const int nv, const long maxdeg){ len_t idx = tbr->lmps[pos]; len_t * hm = tbr->hm[idx]+OFFSET; len_t len = tbr->hm[idx][LENGTH]; /* printf ("len=%d\n",len); */ long i; long N = nrows * matrix->ncols ; long k = 0; /* printf("["); */ for(i = 0; i < matrix->ncols; i++){ if (k < len) { int b = is_larger_exponent_bs(bht,hm[len-1-k],evi,lmb + i * nv,nv); while (b < 0 && k < len-2) { k++; b = is_larger_exponent_bs(bht,hm[len-1-k],evi,lmb + i * nv,nv); } if(!b){ /* equal_exponent */ matrix->dense_mat[N + i] = tbr->cf_32[tbr->hm[idx][COEFFS]][len-1-k]; /* printf("%u, ",matrix->dense_mat[N + i]); */ k++; } } } /* printf("]\n"); */ } /** idx is the position in the GB len is the length of the pol **/ static inline void copy_poly_in_matrix_from_bs_8(sp_matfglm_t* matrix, long nrows, bs_t *bs, ht_t *ht, long idx, long len, long start, long pos, int32_t *lmb, const int nv, const long fc){ int32_t j; long end = start + pos; long N = nrows * (matrix->ncols) - (start + 1); if((len) == matrix->ncols + 1){ const bl_t bi = bs->lmps[idx]; long k = 0; for(j = start + 1; j < end; j++){ long ctmp = bs->cf_8[bs->hm[bi][COEFFS]][len - k - 1]; k++; matrix->dense_mat[N + j] = fc - ctmp; } } else{ if(1==0 && is_equal_exponent_dm(bs, ht, idx, 1, lmb+((end-start-2)*nv), nv)){ const bl_t bi = bs->lmps[idx]; long k = 0; for(j = start + 1; j < end; j++){ long ctmp = bs->cf_8[bs->hm[bi][COEFFS]][len - k]; k++; matrix->dense_mat[N + j] = fc - ctmp; //bcf[(end + start) - j]; } } else{ long i; long N = nrows * matrix->ncols ; long k = 0; const bl_t bi = bs->lmps[idx]; for(i = 0; i < matrix->ncols; i++){ int boo = is_equal_exponent_dm(bs, ht, idx, len - k - 1, //pos-1-k, lmb + i * nv, nv); if(boo){ long ctmp = bs->cf_8[bs->hm[bi][COEFFS]][len - k - 1]; matrix->dense_mat[N + i] = fc - ctmp; //fc - bcf[end - 1 - k]; k++; } } } } } /** idx is the position in the GB len is the length of the pol **/ static inline void copy_poly_in_matrix_from_bs_16(sp_matfglm_t* matrix, long nrows, bs_t *bs, ht_t *ht, long idx, long len, long start, long pos, int32_t *lmb, const int nv, const long fc){ int32_t j; long end = start + pos; long N = nrows * (matrix->ncols) - (start + 1); if((len) == matrix->ncols + 1){ const bl_t bi = bs->lmps[idx]; long k = 0; for(j = start + 1; j < end; j++){ long ctmp = bs->cf_16[bs->hm[bi][COEFFS]][len - k - 1]; k++; matrix->dense_mat[N + j] = fc - ctmp; } } else{ if(1==0 && is_equal_exponent_dm(bs, ht, idx, 1, lmb+((end-start-2)*nv), nv)){ const bl_t bi = bs->lmps[idx]; long k = 0; for(j = start + 1; j < end; j++){ long ctmp = bs->cf_16[bs->hm[bi][COEFFS]][len - k]; k++; matrix->dense_mat[N + j] = fc - ctmp; //bcf[(end + start) - j]; } } else{ long i; long N = nrows * matrix->ncols ; long k = 0; const bl_t bi = bs->lmps[idx]; for(i = 0; i < matrix->ncols; i++){ int boo = is_equal_exponent_dm(bs, ht, idx, len - k - 1, //pos-1-k, lmb + i * nv, nv); if(boo){ long ctmp = bs->cf_16[bs->hm[bi][COEFFS]][len - k - 1]; matrix->dense_mat[N + i] = fc - ctmp; //fc - bcf[end - 1 - k]; k++; } } } } } /** idx is the position in the GB len is the length of the pol **/ static inline void copy_poly_in_matrix_from_bs_32(sp_matfglm_t* matrix, long nrows, bs_t *bs, ht_t *ht, long idx, long len, long start, long pos, int32_t *lmb, const int nv, const long fc){ int32_t j; long end = start + pos; long N = nrows * (matrix->ncols) - (start + 1); if((len) == matrix->ncols + 1){ const bl_t bi = bs->lmps[idx]; long k = 0; for(j = start + 1; j < end; j++){ long ctmp = bs->cf_32[bs->hm[bi][COEFFS]][len - k - 1]; k++; matrix->dense_mat[N + j] = fc - ctmp; } } else{ if(1==0 && is_equal_exponent_dm(bs, ht, idx, 1, lmb+((end-start-2)*nv), nv)){ const bl_t bi = bs->lmps[idx]; long k = 0; for(j = start + 1; j < end; j++){ long ctmp = bs->cf_32[bs->hm[bi][COEFFS]][len - k]; k++; matrix->dense_mat[N + j] = fc - ctmp; //bcf[(end + start) - j]; } } else{ long i; long N = nrows * matrix->ncols ; long k = 0; const bl_t bi = bs->lmps[idx]; for(i = 0; i < matrix->ncols; i++){ int boo = is_equal_exponent_dm(bs, ht, idx, len - k - 1, //pos-1-k, lmb + i * nv, nv); if(boo){ long ctmp = bs->cf_32[bs->hm[bi][COEFFS]][len - k - 1]; matrix->dense_mat[N + i] = fc - ctmp; //fc - bcf[end - 1 - k]; k++; } } } } } /** length is the length of the GB nvars is the number of variables bexp_lm encodes the leading monomials dquot is a pointer to an integer that will be the dimension of the quotient assumes bexp_lm is for grevlex ordering compared to monomial_basis this function does not assume bexp_lm to be 0-dim. It returns all monomials that can appear in the GB */ static inline int32_t *monomial_basis_enlarged(long length, long nvars, int32_t *bexp_lm, long *dquot){ int32_t maxdeg = sum(bexp_lm+(length-1)*(nvars), nvars); /* basis will contain the monomial basis */ int32_t *basis = calloc(nvars, sizeof(int32_t)); (*dquot) = 0; int32_t deg = 0; if(is_divisible_lexp(nvars, length, basis, bexp_lm)){ free(basis); return NULL; } else{ (*dquot)++; } int32_t *ind = calloc(nvars, sizeof(int32_t)); #ifdef DEBUGHILBERT fprintf(stderr, "new = %ld \n", sum(ind, nvars) + nvars); #endif uint64_t len_newbs = nvars * (sum(ind, nvars) + nvars); int32_t *new_basis = malloc(sizeof(int32_t) * len_newbs); /* generates monomial basis candidates of degree 1 */ int32_t new_length = generate_new_elts_basis(nvars, ind, (*dquot), basis, new_basis, length, bexp_lm); deg++; #ifdef DEBUGHILBERT // display_monomials_from_array(stderr, new_length, new_basis, gens); fprintf(stderr, "%ld new elements.\n", new_length); #endif while(new_length>0 && deg <= maxdeg){ uint64_t len_bs = ((*dquot) + new_length) * (nvars); int32_t *basis2 = realloc(basis, ((*dquot) + new_length) * (nvars) * sizeof(int32_t)); if(basis2==NULL){ fprintf(stderr, "Issue with realloc\n"); exit(1); } basis = basis2; for(long i = 0; i < new_length; i++){ for(long k = 0; k < nvars; k++){ (basis)[((*dquot) + i)*(nvars)+k] = (new_basis)[i*(nvars)+k]; } } update_indices(ind, basis, *dquot, new_length, nvars); (*dquot) += new_length; #ifdef DEBUGHILBERT fprintf(stderr, "Update indices\n"); for(long i = 0; i < nvars; i++) fprintf(stderr, "%ld ", ind[i]); fprintf(stderr, "\n"); fprintf(stderr, "new = %ld \n", sum(ind, nvars) + nvars); #endif len_newbs = nvars * (sum(ind, nvars) + nvars); int32_t *new_basis2 = realloc(new_basis, sizeof(int32_t) * len_newbs); if(new_basis==NULL){ fprintf(stderr, "Issue with realloc\n"); exit(1); } new_basis=new_basis2; new_length = generate_new_elts_basis(nvars, ind, (*dquot), basis, new_basis, length, bexp_lm); deg++; #ifdef DEBUGHILBERT fprintf(stderr, "%ld new elements.\n", new_length); #endif } free(new_basis); free(ind); return basis; } /** lmb is the monomial basis (of the quotient ring) given by ascending order. dquo is the dimension of the quotient. data of gb are given by ascending order. bexp_lm is the leading monomials of gb ; there are bld[0] of them. **/ static inline sp_matfglm_t * build_matrixn(int32_t *lmb, long dquot, int32_t bld, int32_t **blen, int32_t **bexp, int32_t *bcf, int32_t *bexp_lm, const int nv, const long fc){ /* takes monomials in bexp_lm which are reducible by xn */ /*div_xn contains the indices of those monomials*/ int32_t *div_xn = calloc(bld, sizeof(int32_t)); /* len_xn is the number of those monomials. */ long len_xn = get_div_xn(bexp_lm, bld, nv, div_xn); #if DEBUGBUILDMATRIX>0 fprintf(stderr, "\n"); fprintf(stderr, "Number of monomials (in the staircase) which are divisible by x_n = %ld\n", len_xn); for(long i=0; i < len_xn; i++){ fprintf(stderr, "%d, ", div_xn[i]); } fprintf(stderr, "\n"); #endif /* lengths of the polys which we need to build the matrix */ int32_t *len_gb_xn = malloc(sizeof(int32_t) * len_xn); int32_t *start_cf_gb_xn = malloc(sizeof(int32_t) * len_xn); long pos = 0, k = 0; for(long i = 0; i < bld; i++){ if(i==div_xn[k]){ len_gb_xn[k]=(*blen)[i]; start_cf_gb_xn[k]=pos; pos+=(*blen)[i]; k++; } else{ pos+=(*blen)[i]; } } #if DEBUGBUILDMATRIX>0 fprintf(stderr, "Length of polynomials whose leading terms are divisible by x_n\n"); for(long i = 0; i < len_xn; i++){ fprintf(stderr, "%d, ", len_gb_xn[i]); } fprintf(stderr, "\n"); #endif sp_matfglm_t *matrix ALIGNED32 = calloc(1, sizeof(sp_matfglm_t)); matrix->charac = fc; matrix->ncols = dquot; matrix->nrows = len_xn; long len1 = dquot * len_xn; long len2 = dquot - len_xn; if(posix_memalign((void **)&(matrix->dense_mat), 32, sizeof(CF_t)*len1)){ fprintf(stderr, "Problem when allocating matrix->dense_mat\n"); exit(1); } else{ for(long i = 0; i < len1; i++){ matrix->dense_mat[i] = 0; } } if(posix_memalign((void **)&matrix->triv_idx, 32, sizeof(CF_t)*len2)){ fprintf(stderr, "Problem when allocating matrix->triv_idx\n"); exit(1); } else{ for(long i = 0; i < len2; i++){ matrix->triv_idx[i] = 0; } } if(posix_memalign((void **)&matrix->triv_pos, 32, sizeof(CF_t)*len2)){ fprintf(stderr, "Problem when allocating matrix->triv_pos\n"); exit(1); } else{ for(long i = 0; i triv_pos[i] = 0; } } if(posix_memalign((void **)&matrix->dense_idx, 32, sizeof(CF_t)*len_xn)){ fprintf(stderr, "Problem when allocating matrix->dense_idx\n"); exit(1); } else{ for(long i = 0; i < len_xn; i++){ matrix->dense_idx[i] = 0; } } if(posix_memalign((void **)&matrix->dst, 32, sizeof(CF_t)*len_xn)){ fprintf(stderr, "Problem when allocating matrix->dense_idx\n"); exit(1); } else{ for(long i = 0; i < len_xn; i++){ matrix->dst[i] = 0; } } long l_triv = 0; long l_dens = 0; long nrows = 0; long count = 0; for(long i = 0; i < dquot; i++){ long pos = -1; int32_t *exp = lmb + (i * nv); #if DEBUGBUILDMATRIX > 0 display_monomial_full(stderr, nv, NULL, 0, exp); #endif if(member_xxn(exp, lmb + (i * nv), dquot - i, &pos, nv)){ #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => remains in monomial basis\n"); #endif /* mult by xn stays in the basis */ matrix->triv_idx[l_triv] = i; matrix->triv_pos[l_triv] = pos + i; l_triv++; } else{ /* we get now outside the basis */ #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => does NOT remain in monomial basis\n"); #endif matrix->dense_idx[l_dens] = i; l_dens++; if(is_equal_exponent_xxn(exp, bexp_lm+(div_xn[count])*nv, nv)){ copy_poly_in_matrix(matrix, nrows, bcf, bexp, blen, start_cf_gb_xn[count], len_gb_xn[count], lmb, nv, fc); nrows++; count++; if(len_xn < count && i < dquot){ fprintf(stderr, "One should not arrive here (build_matrix)\n"); free(matrix->dense_mat); free(matrix->dense_idx); free(matrix->triv_idx); free(matrix->triv_pos); free(matrix); free(len_gb_xn); free(start_cf_gb_xn); free(div_xn); return NULL; } } else{ fprintf(stderr, "\nStaircase is not generic\n"); fprintf(stderr, "Multiplication by "); display_monomial_full(stderr, nv, NULL, 0, exp); fprintf(stderr, " gets outside the staircase\n"); free(matrix->dense_mat); free(matrix->dense_idx); free(matrix->triv_idx); free(matrix->triv_pos); free(matrix->dst); free(matrix); matrix = NULL; free(len_gb_xn); free(start_cf_gb_xn); free(div_xn); return matrix; } } } /* assumes the entries of matrix->dst are 0 */ for(long i = 0; i < matrix->nrows; i++){ for(long j = matrix->ncols - 1; j >= 0; j--){ if(matrix->dense_mat[i*matrix->ncols + j] == 0){ matrix->dst[i]++; } else{ break; } } } free(len_gb_xn); free(start_cf_gb_xn); free(div_xn); return matrix; } /** lmb is the monomial basis (of the subscpace of the quotient ring) given by ascending order. dquo is the dimension of this subspace. data of gb are given by ascending order. bexp_lm is the leading monomials of gb ; there are bld[0] of them. **/ static inline sp_matfglmcol_t * build_matrixn_colon(int32_t *lmb, long dquot, int32_t bld, int32_t **blen, int32_t **bexp, int32_t *bcf, int32_t *bexp_lm, bs_t *tbr, ht_t *bht, md_t *st, const exp_t * const mul, bs_t * bs, const int nv, const long fc, const long maxdeg, const data_gens_ff_t *gens, uint32_t * leftvector, uint32_t ** leftvectorsparam, long suppsize){ const len_t ebl = bht->ebl; const len_t evl = bht->evl; int32_t *evi = (int *)malloc((unsigned long)nv * sizeof(int)); if (ebl == 0) { for (long i = 1; i < evl; ++i) { evi[i-1] = i; } } else { for (long i = 1; i < ebl; ++i) { evi[i-1] = i; } for (long i = ebl+1; i < evl; ++i) { evi[i-2] = i; } } copy_extrapoly_in_vector(leftvector, dquot, lmb, 1, tbr, bht, evi, st, nv, maxdeg); /* takes monomials in bexp_lm which are reducible by xn */ /* div_xn contains the indices of those monomials*/ int32_t *div_xn = calloc(bld, sizeof(int32_t)); /* div_xn contains the indices of those not reducible by xn*/ int32_t *div_not_xn = calloc(bld, sizeof(int32_t)); /* len_xn is the number of those monomials of degree at most maxdeg+1. */ long len_not_xn = 0; long len_xn = get_div_xn_bounded(bexp_lm, bld, nv, div_xn,div_not_xn, &len_not_xn,maxdeg+1); #if DEBUGBUILDMATRIX>0 fprintf(stderr, "\n"); fprintf(stderr, "Number of monomials (in the Gb) " "which are divisible by x_n " "and with bounded degree: %ld\n", len_xn); for(long i=0; i < len_xn; i++){ fprintf(stderr, "%d, ", div_xn[i]); } fprintf(stderr, "\n"); fprintf(stderr, "Number of monomials (in the Gb) " "which are not divisible by x_n " "and with bounded degree: %ld\n", len_not_xn); for(long i=0; i < len_not_xn; i++){ fprintf(stderr, "%d, ", div_not_xn[i]); } fprintf(stderr, "\n"); #endif long count_lm = 0; /* list of monomials in the staircase that leave the staircase after multiplication by xn and land on a multiple of a leading monomial of the Gb */ long *extranf= calloc (dquot, sizeof(long)); long count_not_lm = 0; /* list of monomials in the staircase that leave the staircase after multiplication by xn and land on zero */ long *zeronf= calloc (dquot, sizeof(long)); long count_zero = 0; for (long i = 0; i < dquot; i++) { long pos = -1; int32_t *exp = lmb + (i * nv); if(member_xxn(exp, lmb + (i * nv), dquot - i, &pos, nv)){ #if DEBUGBUILDMATRIX>0 display_monomial_full(stderr, nv, NULL, 0, exp); fprintf(stderr, " => remains in monomial basis\n"); #endif } else{ /* we get now outside the basis */ #if DEBUGBUILDMATRIX > 0 display_monomial_full(stderr, nv, NULL, 0, exp); fprintf(stderr, " => does NOT remain in monomial basis"); #endif if(is_equal_exponent_xxn(exp, bexp_lm+(div_xn[count_lm])*nv, nv)){ count_lm++; #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => land on a leading monomial\n"); #endif } else{ int is_divisible = 0; for(long j = 0; j < len_xn; j++) { if(is_divisible_exponent_xxn(exp, bexp_lm+(div_xn[j])*nv, nv)){ extranf[count_not_lm]=i; count_not_lm++; #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => land on a MULTIPLE of a leading monomial\n"); #endif is_divisible = 1; break; } } if (!is_divisible) { #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => land on 0\n"); #endif zeronf[count_zero]=i; count_zero++; } } } } printf ("Number of extra normal forms for the matrix to compute: %ld\n",count_not_lm); printf ("Number of extra normal forms for the vectors to compute: %d\n",2*nv-2); /* Computation of the extra normal forms */ /* count_not_lm monomials to reduce * each has length 1 */ /* 2*(nv-1) shifts of phi to reduce * each has the same length as phi */ long tobereduced = count_not_lm + 2*nv-2; int32_t* lens=(int32_t *) (malloc(sizeof(int32_t) * tobereduced)); int32_t* exps = (int32_t *) (malloc(sizeof(int32_t) * (count_not_lm + suppsize * (2*nv-2)) * nv)); int32_t* cfs = (int32_t *) (malloc(sizeof(int32_t) * (count_not_lm + suppsize * (2*nv-2)))); /* pure monomials to be reduced */ for (long i = 0; i < count_not_lm;i++){ lens[i]=1; cfs[i]=1; long j= extranf[i]; for (long k = 0; k < nv-1; k++) { exps[i*nv+k]=lmb[j*nv+k]; } exps[i*nv+nv-1]=lmb[j*nv+nv-1]+1; } /* shifts of to be reduced */ len_t idx = tbr->lmps[1]; /* printf ("idx=%d\n",idx); */ len_t * hm = tbr->hm[idx]+OFFSET; /* len_t len = tbr->hm[idx][LENGTH]; */ for (long i = 0; i < 2*nv-2;i++){ lens[count_not_lm + i]=suppsize; for (long j = 0; j < suppsize; j++) { cfs[count_not_lm + i*suppsize + j]=tbr->cf_32[tbr->hm[idx][COEFFS]][j]; for (long k = 0; k < nv-1; k++) { int32_t cpt = 0; if (i == k) { cpt = 1; } else if (i == nv - 1 + k) { cpt = 2; } exps[(count_not_lm + i*suppsize+j)*nv+k]=bht->ev[hm[j]][evi[k]] + cpt; } exps[(count_not_lm + i*suppsize+j)*nv+nv-1]=bht->ev[hm[j]][evi[nv-1]]; } } tbr = initialize_basis(st); tbr->ht = bht; #if REDUCTION_ALLINONE import_input_data(tbr, st, 0, tobereduced, lens, exps, (void *)cfs, NULL); tbr->ld = tbr->lml = tobereduced; /* printf ("%ld imported\n",tobereduced); */ for (int k = 0; k < tobereduced; ++k) { tbr->lmps[k] = k; /* fix input element in tbr */ } /* printf ("polynomials to be reduced\n"); */ /* print_msolve_polynomials_ff(stdout, 0, tbr->lml, tbr, bht, */ /* st, gens->vnames, 0); */ int32_t err = 0; tbr = core_nf(tbr, st, mul, bs, &err); if (err) { printf("Problem with normalform, stopped computation.\n"); exit(1); } /* printf ("reductions\n"); */ /* print_msolve_polynomials_ff(stdout, tobereduced, tbr->lml, tbr, bht, */ /* st, gens->vnames, 0); */ #endif printf ("Number of zero normal forms: %ld\n",count_zero); /* lengths of the polys which we need to build the matrix */ int32_t *len_gb_xn = malloc(sizeof(int32_t) * len_xn); int32_t *start_cf_gb_xn = malloc(sizeof(int32_t) * len_xn); long pos = 0, k = 0; for(long i = 0; i < bld; i++){ if(i==div_xn[k]){ len_gb_xn[k]=(*blen)[i]; start_cf_gb_xn[k]=pos; pos+=(*blen)[i]; k++; } else{ pos+=(*blen)[i]; } } #if DEBUGBUILDMATRIX > 0 fprintf(stderr, "Length of polynomials whose leading terms are divisible by x_n\n"); for(long i = 0; i < len_xn-1; i++){ fprintf(stderr, "%u, ", len_gb_xn[i]); } fprintf(stderr, "%u\n", len_gb_xn[len_xn-1]); #endif sp_matfglmcol_t *matrix ALIGNED32 = calloc(1, sizeof(sp_matfglmcol_t)); matrix->charac = fc; matrix->ncols = dquot; matrix->nzero = count_zero; matrix->nrows = len_xn + count_not_lm; long len1 = dquot * (len_xn + count_not_lm); long len2 = dquot - (len_xn + count_not_lm + count_zero); if(posix_memalign((void **)&(matrix->dense_mat), 32, sizeof(CF_t)*len1)){ fprintf(stderr, "Problem when allocating matrix->dense_mat\n"); exit(1); } else{ for(long i = 0; i < len1; i++){ matrix->dense_mat[i] = 0; } } if(posix_memalign((void **)&matrix->triv_idx, 32, sizeof(CF_t)*len2)){ fprintf(stderr, "Problem when allocating matrix->triv_idx\n"); exit(1); } else{ for(long i = 0; i < len2; i++){ matrix->triv_idx[i] = 0; } } if(posix_memalign((void **)&matrix->triv_pos, 32, sizeof(CF_t)*len2)){ fprintf(stderr, "Problem when allocating matrix->triv_pos\n"); exit(1); } else{ for(long i = 0; i triv_pos[i] = 0; } } if(posix_memalign((void **)&matrix->zero_idx, 32, sizeof(CF_t)*count_zero)){ fprintf(stderr, "Problem when allocating matrix->zero_idx\n"); exit(1); } else{ for(long i = 0; i < count_zero; i++){ matrix->zero_idx[i] = 0; } } if(posix_memalign((void **)&matrix->dense_idx, 32, sizeof(CF_t)*(len_xn + count_not_lm))){ fprintf(stderr, "Problem when allocating matrix->dense_idx\n"); exit(1); } else{ for(long i = 0; i < len_xn + count_not_lm; i++){ matrix->dense_idx[i] = 0; } } if(posix_memalign((void **)&matrix->dst, 32, sizeof(CF_t)*(len_xn + count_not_lm))){ fprintf(stderr, "Problem when allocating matrix->dense_idx\n"); exit(1); } else{ for(long i = 0; i < len_xn + count_not_lm; i++){ matrix->dst[i] = 0; } } long l_triv = 0; long l_dens = 0; long l_zero = 0; long nrows = 0; long count = 0; long count_nf = 0; for(long i = 0; i < dquot; i++){ long pos = -1; int32_t *exp = lmb + (i * nv); /* display_monomial_full(stderr, nv, NULL, 0, exp); */ if(member_xxn(exp, lmb + (i * nv), dquot - i, &pos, nv)){ #if DEBUGBUILDMATRIX > 0 display_monomial_full(stderr, nv, NULL, 0, exp); fprintf(stderr, " => remains in monomial basis\n"); #endif /* mult by xn stays in the basis */ matrix->triv_idx[l_triv] = i; matrix->triv_pos[l_triv] = pos + i; l_triv++; } else{ /* we get now outside the basis */ #if DEBUGBUILDMATRIX > 0 display_monomial_full(stderr, nv, NULL, 0, exp); fprintf(stderr, " => does NOT remain in monomial basis"); #endif if (i == zeronf[l_zero]){ #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => land on 0\n"); printf ("zero row #%ld in row #%ld\n",l_zero,i); #endif matrix->zero_idx[l_zero] = i; l_zero++; } else { matrix->dense_idx[l_dens] = i; l_dens++; if(is_equal_exponent_xxn(exp, bexp_lm+(div_xn[count])*nv, nv)){ #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => land on a leading monomial\n"); #endif copy_poly_in_matrixcol(matrix, nrows, bcf, bexp, blen, start_cf_gb_xn[count], len_gb_xn[count], lmb, nv, fc); nrows++; count++; if(len_xn < count && i < dquot){ fprintf(stderr, "One should not arrive here (build_matrix)\n"); free(lens); free(exps); free(cfs); free(matrix->dense_mat); free(matrix->dense_idx); free(matrix->triv_idx); free(matrix->triv_pos); free(matrix->zero_idx); free(matrix); free(evi); free(len_gb_xn); free(start_cf_gb_xn); free(div_xn); free(div_not_xn); return NULL; } } else if (i == extranf[count_nf]){ #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => land on a MULTIPLE of a leading monomial\n"); #endif #if REDUCTION_ALLINONE copy_extrapoly_in_matrixcol(matrix, nrows, lmb, tobereduced + count_nf, tbr, bht, evi, st, nv, maxdeg); #else /* reduction one by one */ int success; import_input_data(tbr, st, count_nf, count_nf+1, lens, exps, (void *)cfs, NULL); tbr->ld = tbr->lml = 1; /* printf ("1 imported\n"); */ for (int k = 0; k < 1; ++k) { tbr->lmps[k] = k; /* fix input element in tbr */ } /* printf ("mononomial to be reduced\n"); */ /* print_msolve_polynomials_ff(stdout, 0, tbr->lml, tbr, bht, */ /* st, gens->vnames, 0); */ success = core_nf(&tbr, &bht, &st, mul, bs); if (!success) { printf("Problem with normalform, stopped computation.\n"); exit(1); } /* printf ("reduction\n"); */ /* print_msolve_polynomials_ff(stdout, 1, tbr->lml, tbr, bht, */ /* st, gens->vnames, 0); */ copy_extrapoly_in_matrixcol(matrix, nrows, lmb, 1, tbr, bht, evi, st, nv, maxdeg); #endif nrows++; count_nf++; } } } } /* printf ("matrix finished\n[\n"); */ /* assumes the entries of matrix->dst are 0 */ for(long i = 0; i < matrix->nrows; i++){ for(long j = matrix->ncols - 1; j >= 0; j--){ if(matrix->dense_mat[i*matrix->ncols + j] == 0){ matrix->dst[i]++; /* printf ("%d, ",matrix->dst[i]); */ } else{ break; } } } #if REDUCTION_ALLINONE for (long i = 0; i < 2*nv - 2; i++) { copy_extrapoly_in_vector(leftvectorsparam[i], dquot, lmb, tobereduced + count_not_lm + i, tbr, bht, evi, st, nv, maxdeg); } #else /* the shifts of phi are now reduced */ tbr = initialize_basis(st); tbr->ht = bht; import_input_data(tbr, st, count_not_lm, tobereduced, lens, exps, (void *)cfs, NULL); tbr->ld = tbr->lml = 2*nv-2; /* printf ("%d imported\n",2*nv-2); */ for (int k = 0; k < 2*nv-2; ++k) { tbr->lmps[k] = k; /* fix input element in tbr */ } /* printf ("shifts of phi to be reduced\n"); */ /* print_msolve_polynomials_ff(stdout, 0, tbr->lml, tbr, bht, */ /* st, gens->vnames, 0); */ int success = core_nf(&tbr, &bht, &st, mul, bs); if (!success) { printf("Problem with normalform, stopped computation.\n"); exit(1); } /* printf ("reductions\n"); */ /* print_msolve_polynomials_ff(stdout, 2*nv-2, tbr->lml, tbr, bht, */ /* st, gens->vnames, 0); */ for (long i = 0; i < 2*nv - 2; i++) { copy_extrapoly_in_vector(leftvectorsparam[i], dquot, lmb, 2*nv-2+i, tbr, bht, evi, st, nv, maxdeg); } #endif free(lens); free(exps); free(cfs); free(evi); free(len_gb_xn); free(start_cf_gb_xn); free(div_xn); free(div_not_xn); return matrix; } /** lmb is the monomial basis (of the subscpace of the quotient ring) given by ascending order. dquo is the dimension of this subspace. data of gb are given by ascending order. bexp_lm is the leading monomials of gb ; there are bld[0] of them. **/ static inline sp_matfglmcol_t * build_matrixn_colon_no_zero(int32_t *lmb, long dquot, int32_t bld, int32_t **blen, int32_t **bexp, int32_t *bcf, int32_t *bexp_lm, bs_t *tbr, ht_t *bht, md_t *st, const exp_t * const mul, bs_t * bs, const int nv, const long fc, const long maxdeg, const data_gens_ff_t *gens, uint32_t * leftvector, uint32_t ** leftvectorsparam, long suppsize){ const len_t ebl = bht->ebl; const len_t evl = bht->evl; int32_t *evi = (int *)malloc((unsigned long)nv * sizeof(int)); if (ebl == 0) { for (long i = 1; i < evl; ++i) { evi[i-1] = i; } } else { for (long i = 1; i < ebl; ++i) { evi[i-1] = i; } for (long i = ebl+1; i < evl; ++i) { evi[i-2] = i; } } for (long i = 1; i < tbr->lml; i++) { len_t idx = tbr->lmps[i]; len_t * hm = tbr->hm[idx]+OFFSET; len_t len = tbr->hm[idx][LENGTH]; long k = 0; for (long j = 0; j < 5; j++) { while (!is_equal_exponent_bs (bht,hm[len-1-j],evi,lmb+k*nv,nv)) { k++; } } } copy_extrapoly_in_vector_no_zero(leftvector, dquot, lmb, 1, tbr, bht, evi, st, nv, maxdeg); /* takes monomials in bexp_lm which are reducible by xn */ /* div_xn contains the indices of those monomials*/ int32_t *div_xn = calloc(bld, sizeof(int32_t)); /* div_xn contains the indices of those not reducible by xn*/ int32_t *div_not_xn = calloc(bld, sizeof(int32_t)); /* len_xn is the number of those monomials of degree at most maxdeg+1. */ /* int is_divisible = 0; */ long len_not_xn = 0; long len_xn = get_div_xn_bounded(bexp_lm, bld, nv, div_xn,div_not_xn, &len_not_xn,maxdeg+1); #if DEBUGBUILDMATRIX > 0 fprintf(stderr, "\n"); fprintf(stderr, "Number of monomials (in the Gb) " "which are divisible by x_n " "and with bounded degree: %ld\n", len_xn); for(long i=0; i < len_xn; i++){ fprintf(stderr, "%d, ", div_xn[i]); } fprintf(stderr, "\n"); fprintf(stderr, "Number of monomials (in the Gb) " "which are not divisible by x_n " "and with bounded degree: %ld\n", len_not_xn); for(long i=0; i < len_not_xn; i++){ fprintf(stderr, "%d, ", div_not_xn[i]); } fprintf(stderr, "\n"); #endif long count_lm = 0; /* list of monomials in the staircase that leave the staircase after multiplication by xn and land on a multiple of a leading monomial of the Gb */ long *extranf= calloc (dquot, sizeof(long)); long count_not_lm = 0; /* list of monomials in the staircase that leave the staircase after multiplication by xn and land on zero */ /* long *zeronf= calloc (dquot, sizeof(long)); */ /* long count_zero = 0; */ for (long i = 0; i < dquot; i++) { long pos = -1; int32_t *exp = lmb + (i * nv); if(member_xxn(exp, lmb + (i * nv), dquot - i, &pos, nv)){ #if DEBUGBUILDMATRIX > 0 display_monomial_full(stderr, nv, NULL, 0, exp); fprintf(stderr, " => remains in monomial basis\n"); #endif } else{ /* we get now outside the basis */ #if DEBUGBUILDMATRIX > 0 display_monomial_full(stderr, nv, NULL, 0, exp); fprintf(stderr, " => does NOT remain in monomial basis"); #endif if(is_equal_exponent_xxn(exp, bexp_lm+(div_xn[count_lm])*nv, nv)){ count_lm++; #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => land on a leading monomial\n"); #endif } else{ for(long j = 0; j < len_xn; j++) { if(is_divisible_exponent_xxn(exp, bexp_lm+(div_xn[j])*nv, nv)){ extranf[count_not_lm]=i; count_not_lm++; #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => land on a MULTIPLE of a leading monomial\n"); #endif /* is_divisible = 1; */ break; } } /* if (!is_divisible) { */ /* #if DEBUGBUILDMATRIX > 0 */ /* fprintf(stderr, " => land on 0\n"); */ /* #endif */ /* zeronf[count_zero]=i; */ /* count_zero++; */ /* } */ } } } printf ("Number of extra normal forms for the matrix to compute: %ld\n",count_not_lm); printf ("Number of extra normal forms for the vectors to compute: %d\n",2*nv-2); /* Computation of the extra normal forms */ /* count_not_lm monomials to reduce * each has length 1 */ /* 2*(nv-1) shifts of phi to reduce * each has the same length as phi */ long tobereduced = count_not_lm + 2*nv-2; int32_t* lens=(int32_t *) (malloc(sizeof(int32_t) * tobereduced)); int32_t* exps = (int32_t *) (malloc(sizeof(int32_t) * (count_not_lm + suppsize * (2*nv-2)) * nv)); int32_t* cfs = (int32_t *) (malloc(sizeof(int32_t) * (count_not_lm + suppsize * (2*nv-2)))); /* pure monomials to be reduced */ for (long i = 0; i < count_not_lm;i++){ lens[i]=1; cfs[i]=1; long j= extranf[i]; for (long k = 0; k < nv-1; k++) { exps[i*nv+k]=lmb[j*nv+k]; } exps[i*nv+nv-1]=lmb[j*nv+nv-1]+1; } /* shifts of to be reduced */ len_t idx = tbr->lmps[1]; len_t * hm = tbr->hm[idx]+OFFSET; /* len_t len = tbr->hm[idx][LENGTH]; */ for (long i = 0; i < 2*nv-2;i++){ lens[count_not_lm + i]=suppsize; for (long j = 0; j < suppsize; j++) { cfs[count_not_lm + i*suppsize + j]=tbr->cf_32[tbr->hm[idx][COEFFS]][j]; for (long k = 0; k < nv-1; k++) { int32_t cpt = 0; if (i == k) { cpt = 1; } else if (i == nv - 1 + k) { cpt = 2; } exps[(count_not_lm + i*suppsize+j)*nv+k]=bht->ev[hm[j]][evi[k]] + cpt; } exps[(count_not_lm + i*suppsize+j)*nv+nv-1]=bht->ev[hm[j]][evi[nv-1]]; } } tbr = initialize_basis(st); tbr->ht = bht; import_input_data(tbr, st, 0, tobereduced, lens, exps, (void *)cfs, NULL); tbr->ld = tbr->lml = tobereduced; /* printf ("%ld imported\n",tobereduced); */ for (int k = 0; k < tobereduced; ++k) { tbr->lmps[k] = k; /* fix input element in tbr */ } /* printf ("polynomials to be reduced\n"); */ /* print_msolve_polynomials_ff(stdout, 0, tbr->lml, tbr, bht, */ /* st, gens->vnames, 0); */ int32_t err = 0; tbr = core_nf(tbr, st, mul, bs, &err); if (err) { printf("Problem with normalform, stopped computation.\n"); exit(1); } /* printf ("reductions\n"); */ /* print_msolve_polynomials_ff(stdout, tobereduced, tbr->lml, tbr, bht, */ /* st, gens->vnames, 0); */ /* printf ("Number of zero normal forms: %ld\n",count_zero); */ /* lengths of the polys which we need to build the matrix */ int32_t *len_gb_xn = malloc(sizeof(int32_t) * len_xn); int32_t *start_cf_gb_xn = malloc(sizeof(int32_t) * len_xn); long pos = 0, k = 0; for(long i = 0; i < bld; i++){ if(i==div_xn[k]){ len_gb_xn[k]=(*blen)[i]; start_cf_gb_xn[k]=pos; pos+=(*blen)[i]; k++; } else{ pos+=(*blen)[i]; } } #if DEBUGBUILDMATRIX > 0 fprintf(stderr, "Length of polynomials whose leading terms are divisible by x_n\n"); for(long i = 0; i < len_xn-1; i++){ fprintf(stderr, "%u, ", len_gb_xn[i]); } fprintf(stderr, "%u\n", len_gb_xn[len_xn-1]); #endif sp_matfglmcol_t *matrix ALIGNED32 = calloc(1, sizeof(sp_matfglmcol_t)); matrix->charac = fc; matrix->ncols = dquot; matrix->nzero = 0; /* count_zero; */ matrix->nrows = len_xn + count_not_lm; long len1 = dquot * (len_xn + count_not_lm); long len2 = dquot - (len_xn + count_not_lm /* + count_zero*/); if(posix_memalign((void **)&(matrix->dense_mat), 32, sizeof(CF_t)*len1)){ fprintf(stderr, "Problem when allocating matrix->dense_mat\n"); exit(1); } else{ for(long i = 0; i < len1; i++){ matrix->dense_mat[i] = 0; } } if(posix_memalign((void **)&matrix->triv_idx, 32, sizeof(CF_t)*len2)){ fprintf(stderr, "Problem when allocating matrix->triv_idx\n"); exit(1); } else{ for(long i = 0; i < len2; i++){ matrix->triv_idx[i] = 0; } } if(posix_memalign((void **)&matrix->triv_pos, 32, sizeof(CF_t)*len2)){ fprintf(stderr, "Problem when allocating matrix->triv_pos\n"); exit(1); } else{ for(long i = 0; i triv_pos[i] = 0; } } /* if(posix_memalign((void **)&matrix->zero_idx, 32, sizeof(CF_t)*count_zero)){ */ /* fprintf(stderr, "Problem when allocating matrix->zero_idx\n"); */ /* exit(1); */ /* } */ /* else{ */ /* for(long i = 0; i < count_zero; i++){ */ /* matrix->zero_idx[i] = 0; */ /* } */ /* } */ if(posix_memalign((void **)&matrix->dense_idx, 32, sizeof(CF_t)*(len_xn + count_not_lm))){ fprintf(stderr, "Problem when allocating matrix->dense_idx\n"); exit(1); } else{ for(long i = 0; i < len_xn + count_not_lm; i++){ matrix->dense_idx[i] = 0; } } if(posix_memalign((void **)&matrix->dst, 32, sizeof(CF_t)*(len_xn + count_not_lm))){ fprintf(stderr, "Problem when allocating matrix->dense_idx\n"); exit(1); } else{ for(long i = 0; i < len_xn + count_not_lm; i++){ matrix->dst[i] = 0; } } for (long i = count_not_lm; i < tbr->lml; i++) { len_t idx = tbr->lmps[i]; len_t * hm = tbr->hm[idx]+OFFSET; len_t len = tbr->hm[idx][LENGTH]; long k = 0; for (long j = 0; j < 5; j++) { while (!is_equal_exponent_bs (bht,hm[len-1-j],evi,lmb+k*nv,nv)) { k++; } } } long l_triv = 0; long l_dens = 0; /* long l_zero = 0; */ long nrows = 0; long count = 0; long count_nf = 0; for(long i = 0; i < dquot; i++){ long pos = -1; int32_t *exp = lmb + (i * nv); /* display_monomial_full(stderr, nv, NULL, 0, exp); */ if(member_xxn(exp, lmb + (i * nv), dquot - i, &pos, nv)){ #if DEBUGBUILDMATRIX > 0 display_monomial_full(stderr, nv, NULL, 0, exp); fprintf(stderr, " => remains in monomial basis\n"); #endif /* mult by xn stays in the basis */ matrix->triv_idx[l_triv] = i; matrix->triv_pos[l_triv] = pos + i; l_triv++; } else{ /* we get now outside the basis */ #if DEBUGBUILDMATRIX > 0 display_monomial_full(stderr, nv, NULL, 0, exp); fprintf(stderr, " => does NOT remain in monomial basis"); #endif /* if (i == zeronf[l_zero]){ */ /* #if DEBUGBUILDMATRIX > 0 */ /* fprintf(stderr, " => land on 0\n"); */ /* printf ("zero row #%ld in row #%ld\n",l_zero,i); */ /* #endif */ /* matrix->zero_idx[l_zero] = i; */ /* l_zero++; */ /* } */ /* else { */ matrix->dense_idx[l_dens] = i; l_dens++; if(is_equal_exponent_xxn(exp, bexp_lm+(div_xn[count])*nv, nv)){ #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => land on a leading monomial\n"); #endif copy_poly_in_matrixcol_no_zero(matrix, nrows, bcf, bexp, blen, start_cf_gb_xn[count], len_gb_xn[count], lmb, nv, fc); nrows++; count++; if(len_xn < count && i < dquot){ fprintf(stderr, "One should not arrive here (build_matrix)\n"); free(lens); free(exps); free(cfs); free(matrix->dense_mat); free(matrix->dense_idx); free(matrix->triv_idx); free(matrix->triv_pos); /* free(matrix->zero_idx); */ free(matrix); free(evi); free(len_gb_xn); free(start_cf_gb_xn); free(div_xn); free(div_not_xn); return NULL; } } else if (i == extranf[count_nf]){ #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => land on a MULTIPLE of a leading monomial\n"); #endif copy_extrapoly_in_matrixcol_no_zero(matrix, nrows, lmb, tobereduced + count_nf, tbr, bht, evi, st, nv, maxdeg); nrows++; count_nf++; } } } /* printf ("matrix finished\n[\n"); */ /* for (long i = 0; i< matrix->nrows; i++){ */ /* printf ("["); */ /* for (long j = 0; j < matrix->ncols; j++){ */ /* printf ("%d, ", matrix->dense_mat[i*matrix->ncols+j]); */ /* } */ /* printf ("]\n"); */ /* } */ /* printf("]\n"); */ /* assumes the entries of matrix->dst are 0 */ for(long i = 0; i < matrix->nrows; i++){ for(long j = matrix->ncols - 1; j >= 0; j--){ if(matrix->dense_mat[i*matrix->ncols + j] == 0){ matrix->dst[i]++; /* printf ("%d, ",matrix->dst[i]); */ } else{ break; } } } for (long i = 0; i < 2*nv - 2; i++) { copy_extrapoly_in_vector_no_zero(leftvectorsparam[i], dquot, lmb, tobereduced + count_not_lm + i, tbr, bht, evi, st, nv, maxdeg); } free(lens); free(exps); free(cfs); free(evi); free(len_gb_xn); free(start_cf_gb_xn); free(div_xn); free(div_not_xn); return matrix; } /** lmb is the monomial basis (of the quotient ring) given by ascending order. dquo is the dimension of the quotient. data of gb are given by ascending order. bexp_lm is the leading monomials of gb ; there are bld[0] of them. **/ static inline sp_matfglm_t * build_matrixn_trace(int32_t **bdiv_xn, int32_t **blen_gb_xn, int32_t **bstart_cf_gb_xn, int32_t *lmb, long dquot, int32_t bld, int32_t **blen, int32_t **bexp, int32_t *bcf, int32_t *bexp_lm, const int nv, const long fc){ *bdiv_xn = calloc((unsigned long)bld, sizeof(int32_t)); int32_t *div_xn = *bdiv_xn; long len_xn = get_div_xn(bexp_lm, bld, nv, div_xn); #if DEBUGBUILDMATRIX>0 fprintf(stderr, "\n"); fprintf(stderr, "Number of monomials (in the staircase) which are divisible by x_n = %ld\n", len_xn); for(long i=0; i < len_xn; i++){ fprintf(stderr, "%d, ", div_xn[i]); } fprintf(stderr, "\n"); #endif *blen_gb_xn = malloc(sizeof(int32_t) * len_xn); int32_t *len_gb_xn = *blen_gb_xn; *bstart_cf_gb_xn = malloc(sizeof(int32_t) * len_xn); int32_t *start_cf_gb_xn = *bstart_cf_gb_xn; long pos = 0, k = 0; for(long i = 0; i < bld; i++){ if(i==div_xn[k]){ len_gb_xn[k]=(*blen)[i]; start_cf_gb_xn[k]=pos; pos+=(*blen)[i]; k++; } else{ pos+=(*blen)[i]; } } #if DEBUGBUILDMATRIX>0 fprintf(stderr, "Length ofpolynomials whose leading terms is divisible by x_n\n"); for(long i = 0; i < len_xn; i++){ fprintf(stderr, "%d, ", len_gb_xn[i]); } fprintf(stderr, "\n"); #endif sp_matfglm_t *matrix ALIGNED32 = calloc(1, sizeof(sp_matfglm_t)); matrix->charac = fc; matrix->ncols = dquot; matrix->nrows = len_xn; long len1 = dquot * len_xn; long len2 = dquot - len_xn; if(posix_memalign((void **)&matrix->dense_mat, 32, sizeof(CF_t)*len1)){ fprintf(stderr, "Problem when allocating matrix->dense_mat\n"); exit(1); } else{ for(long i = 0; i < len1; i++){ matrix->dense_mat[i] = 0; } } if(posix_memalign((void **)&matrix->triv_idx, 32, sizeof(CF_t)*(dquot - len_xn))){ fprintf(stderr, "Problem when allocating matrix->triv_idx\n"); exit(1); } else{ for(long i = 0; i < (dquot-len_xn); i++){ matrix->triv_idx[i] = 0; } } if(posix_memalign((void **)&matrix->triv_pos, 32, sizeof(CF_t)*len2)){ fprintf(stderr, "Problem when allocating matrix->triv_pos\n"); exit(1); } else{ for(long i = 0; i triv_pos[i] = 0; } } if(posix_memalign((void **)&matrix->dense_idx, 32, sizeof(CF_t)*len_xn)){ fprintf(stderr, "Problem when allocating matrix->dense_idx\n"); exit(1); } else{ for(long i = 0; i < len_xn; i++){ matrix->dense_idx[i] = 0; } } if(posix_memalign((void **)&matrix->dst, 32, sizeof(CF_t)*len_xn)){ fprintf(stderr, "Problem when allocating matrix->dense_idx\n"); exit(1); } else{ for(long i = 0; i < len_xn; i++){ matrix->dst[i] = 0; } } long l_triv = 0; long l_dens = 0; long nrows = 0; long count = 0; for(long i = 0; i < dquot; i++){ long pos = -1; int32_t *exp = lmb + (i * nv); #if DEBUGBUILDMATRIX > 0 display_monomial_full(stderr, nv, NULL, 0, exp); // fprintf(stderr, "\n"); #endif if(member_xxn(exp, lmb + (i * nv), dquot - i, &pos, nv)){ #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => remains in monomial basis\n"); #endif matrix->triv_idx[l_triv] = i; matrix->triv_pos[l_triv] = pos + i; l_triv++; } else{ #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => does NOT remain in monomial basis\n"); #endif matrix->dense_idx[l_dens] = i; l_dens++; if(is_equal_exponent_xxn(exp, bexp_lm+(div_xn[count])*nv, nv)){ copy_poly_in_matrix(matrix, nrows, bcf, bexp, blen, start_cf_gb_xn[count], len_gb_xn[count], lmb, nv, fc); nrows++; count++; if(len_xn < count && i < dquot){ fprintf(stderr, "One should not arrive here (build_matrix)\n"); free(matrix->dense_mat); free(matrix->dense_idx); free(matrix->triv_idx); free(matrix->triv_pos); free(matrix); free(len_gb_xn); free(start_cf_gb_xn); free(div_xn); return NULL; } } else{ fprintf(stderr, "Staircase is not generic\n"); fprintf(stderr, "Multiplication by "); display_monomial_full(stderr, nv, NULL, 0, exp); fprintf(stderr, " gets outside the staircase\n"); free(matrix->dense_mat); free(matrix->dense_idx); free(matrix->triv_idx); free(matrix->triv_pos); free(matrix->dst); free(matrix); free(len_gb_xn); free(start_cf_gb_xn); free(div_xn); return NULL; } } } for(long i = 0; i < matrix->nrows; i++){ for(long j = matrix->ncols - 1; j >= 0; j--){ if(matrix->dense_mat[i*matrix->ncols + j] == 0){ matrix->dst[i]++; } else{ break; } } } return matrix; } /** lmb is the monommial basis (of the quotient ring) given by ascending order. dquo is the dimension of the quotient. data of gb are given by ascending order. bexp_lm is the leading monomials of gb ; there are bld[0] of them. **/ static inline sp_matfglm_t * build_matrixn_from_bs(int32_t *lmb, long dquot, bs_t *bs, ht_t *ht, int32_t *bexp_lm, const int nv, const long fc){ int32_t *div_xn = calloc(bs->lml, sizeof(int32_t)); long len_xn = get_div_xn(bexp_lm, bs->lml, nv, div_xn); #if DEBUGBUILDMATRIX>0 fprintf(stderr, "\n"); fprintf(stderr, "Number of monomials (in the staircase) which are divisible by x_n = %ld\n", len_xn); for(long i=0; i < len_xn; i++){ fprintf(stderr, "%d, ", div_xn[i]); } fprintf(stderr, "\n"); #endif int32_t *len_gb_xn = malloc(sizeof(int32_t) * len_xn); int32_t *start_cf_gb_xn = malloc(sizeof(int32_t) * len_xn); long pos = 0, k = 0; for(long i = 0; i < bs->lml; i++){ long len = bs->hm[bs->lmps[i]][LENGTH]; if(i==div_xn[k]){ len_gb_xn[k]=len; start_cf_gb_xn[k]=pos; pos+=len; k++; } else{ pos+=len; } } #if DEBUGBUILDMATRIX>0 fprintf(stderr, "Length ofpolynomials whose leading terms is divisible by x_n\n"); for(long i = 0; i < len_xn; i++){ fprintf(stderr, "%d, ", len_gb_xn[i]); } fprintf(stderr, "\n"); #endif sp_matfglm_t *matrix ALIGNED32 = calloc(1, sizeof(sp_matfglm_t)); matrix->charac = fc; matrix->ncols = dquot; matrix->nrows = len_xn; long len1 = dquot * len_xn; long len2 = dquot - len_xn; if(posix_memalign((void **)&matrix->dense_mat, 32, sizeof(CF_t)*len1)){ fprintf(stderr, "Problem when allocating matrix->dense_mat\n"); exit(1); } else{ for(long i = 0; i < len1; i++){ matrix->dense_mat[i] = 0; } } if(posix_memalign((void **)&matrix->triv_idx, 32, sizeof(CF_t)*(dquot - len_xn))){ fprintf(stderr, "Problem when allocating matrix->triv_idx\n"); exit(1); } else{ for(long i = 0; i < (dquot-len_xn); i++){ matrix->triv_idx[i] = 0; } } if(posix_memalign((void **)&matrix->triv_pos, 32, sizeof(CF_t)*len2)){ fprintf(stderr, "Problem when allocating matrix->triv_pos\n"); exit(1); } else{ for(long i = 0; i triv_pos[i] = 0; } } if(posix_memalign((void **)&matrix->dense_idx, 32, sizeof(CF_t)*len_xn)){ fprintf(stderr, "Problem when allocating matrix->dense_idx\n"); exit(1); } else{ for(long i = 0; i < len_xn; i++){ matrix->dense_idx[i] = 0; } } if(posix_memalign((void **)&matrix->dst, 32, sizeof(CF_t)*len_xn)){ fprintf(stderr, "Problem when allocating matrix->dense_idx\n"); exit(1); } else{ for(long i = 0; i < len_xn; i++){ matrix->dst[i] = 0; } } long l_triv = 0; long l_dens = 0; long nrows = 0; long count = 0; for(long i = 0; i < dquot; i++){ long pos = -1; int32_t *exp = lmb + (i * nv); #if DEBUGBUILDMATRIX > 0 display_monomial_full(stderr, nv, NULL, 0, exp); // fprintf(stderr, "\n"); #endif if(member_xxn(exp, lmb + (i * nv), dquot - i, &pos, nv)){ #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => remains in monomial basis\n"); #endif matrix->triv_idx[l_triv] = i; matrix->triv_pos[l_triv] = pos + i; l_triv++; } else{ #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => does NOT remain in monomial basis\n"); #endif matrix->dense_idx[l_dens] = i; l_dens++; if(is_equal_exponent_xxn(exp, bexp_lm+(div_xn[count])*nv, nv)){ copy_poly_in_matrix_from_bs(matrix, nrows, bs, ht, //bcf, bexp, blen, div_xn[count], len_gb_xn[count], start_cf_gb_xn[count], len_gb_xn[count], lmb, nv, fc); nrows++; count++; if(len_xn < count && i < dquot){ fprintf(stderr, "One should not arrive here (build_matrix with trace)\n"); free(matrix->dense_mat); free(matrix->dense_idx); free(matrix->triv_idx); free(matrix->triv_pos); free(matrix); free(len_gb_xn); free(start_cf_gb_xn); free(div_xn); return NULL; } } else{ fprintf(stderr, "Staircase is not generic\n"); fprintf(stderr, "Multiplication by "); display_monomial_full(stderr, nv, NULL, 0, exp); fprintf(stderr, " gets outside the staircase\n"); free(matrix->dense_mat); free(matrix->dense_idx); free(matrix->triv_idx); free(matrix->triv_pos); free(matrix->dst); free(matrix); free(len_gb_xn); free(start_cf_gb_xn); free(div_xn); return NULL; } } } for(long i = 0; i < matrix->nrows; i++){ for(long j = matrix->ncols - 1; j >= 0; j--){ if(matrix->dense_mat[i*matrix->ncols + j] == 0){ matrix->dst[i]++; } else{ break; } } } free(len_gb_xn); free(start_cf_gb_xn); free(div_xn); return matrix; } /** lmb is the monommial basis (of the quotient ring) given by ascending order. dquo is the dimension of the quotient. data of gb are given by ascending order. bexp_lm is the leading monomials of gb ; there are bld[0] of them. The matrix is already allocated. div_xn tableau des monomes divisibles par xn len_gb_xn + startc_cf_gb_xn permettent d'avoir les longueurs des polys dont les monomes de tete sont divisibles par xn **/ static inline void build_matrixn_from_bs_trace_application(sp_matfglm_t *matrix, int32_t *div_xn, int32_t *len_gb_xn, int32_t *start_cf_gb_xn, int32_t *lmb, long dquot, bs_t *bs, ht_t *ht, int32_t *bexp_lm, const int nv, const long fc){ long len_xn = matrix->nrows; //get_div_xn(bexp_lm, bs->lml, nv, div_xn); matrix->charac = fc; /* matrix->ncols = dquot; */ /* matrix->nrows = len_xn; */ long len1 = dquot * matrix->nrows; long len2 = dquot - matrix->nrows; for(long i = 0; i < len1; i++){ matrix->dense_mat[i] = 0; } for(long i = 0; i < (dquot-len_xn); i++){ matrix->triv_idx[i] = 0; } for(long i = 0; i triv_pos[i] = 0; } for(long i = 0; i < len_xn; i++){ matrix->dense_idx[i] = 0; } for(long i = 0; i < len_xn; i++){ matrix->dst[i] = 0; } long pos = 0, k = 0; for(long i = 0; i < bs->lml; i++){ long len = bs->hm[bs->lmps[i]][LENGTH]; if(i==div_xn[k]){ len_gb_xn[k]=len; start_cf_gb_xn[k]=pos; pos+=len; k++; } else{ pos+=len; } } long l_triv = 0; long l_dens = 0; long nrows = 0; long count = 0; for(long i = 0; i < dquot; i++){ long pos = -1; int32_t *exp = lmb + (i * nv); #if DEBUGBUILDMATRIX > 0 display_monomial_full(stderr, nv, NULL, 0, exp); #endif if(member_xxn(exp, lmb + (i * nv), dquot - i, &pos, nv)){ #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => remains in monomial basis\n"); #endif matrix->triv_idx[l_triv] = i; matrix->triv_pos[l_triv] = pos + i; l_triv++; } else{ #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => does NOT remain in monomial basis\n"); #endif matrix->dense_idx[l_dens] = i; l_dens++; if(is_equal_exponent_xxn(exp, bexp_lm+(div_xn[count])*nv, nv)){ copy_poly_in_matrix_from_bs(matrix, nrows, bs, ht, //bcf, bexp, blen, div_xn[count], len_gb_xn[count], start_cf_gb_xn[count], len_gb_xn[count], lmb, nv, fc); nrows++; count++; if(len_xn < count && i < dquot){ fprintf(stderr, "One should not arrive here (build_matrix with trace)\n"); free(matrix->dense_mat); free(matrix->dense_idx); free(matrix->triv_idx); free(matrix->triv_pos); free(matrix); free(len_gb_xn); free(start_cf_gb_xn); free(div_xn); exit(1); } } else{ fprintf(stderr, "Staircase is not generic\n"); fprintf(stderr, "Multiplication by "); display_monomial_full(stderr, nv, NULL, 0, exp); fprintf(stderr, " gets outside the staircase\n"); free(matrix->dense_mat); free(matrix->dense_idx); free(matrix->triv_idx); free(matrix->triv_pos); free(matrix->dst); free(matrix); free(len_gb_xn); free(start_cf_gb_xn); free(div_xn); return ; // exit(1); } } } //Ici on support que les entres de matrix->dst sont initialisees a 0 for(long i = 0; i < matrix->nrows; i++){ for(long j = matrix->ncols - 1; j >= 0; j--){ if(matrix->dense_mat[i*matrix->ncols + j] == 0){ matrix->dst[i]++; } else{ break; } } } } static inline sp_matfglm_t * build_matrixn_from_bs_trace(int32_t **bdiv_xn, int32_t **blen_gb_xn, int32_t **bstart_cf_gb_xn, int32_t *lmb, long dquot, bs_t *bs, ht_t *ht, int32_t *bexp_lm, const int nv, const long fc, const int info_level){ *bdiv_xn = calloc((unsigned long)bs->lml, sizeof(int32_t)); int32_t *div_xn = *bdiv_xn; long len_xn = get_div_xn(bexp_lm, bs->lml, nv, div_xn); #if DEBUGBUILDMATRIX>0 fprintf(stderr, "\n"); fprintf(stderr, "Number of monomials (in the staircase) which are divisible by x_n = %ld\n", len_xn); for(long i=0; i < len_xn; i++){ fprintf(stderr, "%d, ", div_xn[i]); } fprintf(stderr, "\n"); #endif *blen_gb_xn = malloc(sizeof(int32_t) * len_xn); int32_t *len_gb_xn = *blen_gb_xn; *bstart_cf_gb_xn = malloc(sizeof(int32_t) * len_xn); int32_t *start_cf_gb_xn = *bstart_cf_gb_xn; long pos = 0, k = 0; for(long i = 0; i < bs->lml; i++){ long len = bs->hm[bs->lmps[i]][LENGTH]; if(i==div_xn[k]){ len_gb_xn[k]=len; start_cf_gb_xn[k]=pos; pos+=len; k++; } else{ pos+=len; } } #if DEBUGBUILDMATRIX>0 fprintf(stderr, "Length of polynomials whose leading terms is divisible by x_n\n"); for(long i = 0; i < len_xn; i++){ fprintf(stderr, "%d, ", len_gb_xn[i]); } fprintf(stderr, "\n"); #endif sp_matfglm_t *matrix ALIGNED32 = calloc(1, sizeof(sp_matfglm_t)); matrix->charac = fc; matrix->ncols = dquot; matrix->nrows = len_xn; long len1 = dquot * len_xn; long len2 = dquot - len_xn; if(posix_memalign((void **)&matrix->dense_mat, 32, sizeof(CF_t)*len1)){ fprintf(stderr, "Problem when allocating matrix->dense_mat\n"); exit(1); } else{ for(long i = 0; i < len1; i++){ matrix->dense_mat[i] = 0; } } if(posix_memalign((void **)&matrix->triv_idx, 32, sizeof(CF_t)*(dquot - len_xn))){ fprintf(stderr, "Problem when allocating matrix->triv_idx\n"); exit(1); } else{ for(long i = 0; i < (dquot-len_xn); i++){ matrix->triv_idx[i] = 0; } } if(posix_memalign((void **)&matrix->triv_pos, 32, sizeof(CF_t)*len2)){ fprintf(stderr, "Problem when allocating matrix->triv_pos\n"); exit(1); } else{ for(long i = 0; i triv_pos[i] = 0; } } if(posix_memalign((void **)&matrix->dense_idx, 32, sizeof(CF_t)*len_xn)){ fprintf(stderr, "Problem when allocating matrix->dense_idx\n"); exit(1); } else{ for(long i = 0; i < len_xn; i++){ matrix->dense_idx[i] = 0; } } if(posix_memalign((void **)&matrix->dst, 32, sizeof(CF_t)*len_xn)){ fprintf(stderr, "Problem when allocating matrix->dense_idx\n"); exit(1); } else{ for(long i = 0; i < len_xn; i++){ matrix->dst[i] = 0; } } long l_triv = 0; long l_dens = 0; long nrows = 0; long count = 0; for(long i = 0; i < dquot; i++){ long pos = -1; int32_t *exp = lmb + (i * nv); #if DEBUGBUILDMATRIX > 0 display_monomial_full(stderr, nv, NULL, 0, exp); // fprintf(stderr, "\n"); #endif if(member_xxn(exp, lmb + (i * nv), dquot - i, &pos, nv)){ #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => remains in monomial basis\n"); #endif matrix->triv_idx[l_triv] = i; matrix->triv_pos[l_triv] = pos + i; l_triv++; } else{ #if DEBUGBUILDMATRIX > 0 fprintf(stderr, " => does NOT remain in monomial basis\n"); #endif int boo = 0; if(count < len_xn){ boo = is_equal_exponent_xxn(exp, bexp_lm+(div_xn[count])*nv, nv); } if(boo){ matrix->dense_idx[l_dens] = i; l_dens++; copy_poly_in_matrix_from_bs(matrix, nrows, bs, ht, div_xn[count], len_gb_xn[count], start_cf_gb_xn[count], len_gb_xn[count], lmb, nv, fc); nrows++; count++; if(len_xn < count && i < dquot){ if(info_level){ fprintf(stderr, "Staircase is not generic (1 => explain better)\n"); } free(matrix->dense_mat); free(matrix->dense_idx); free(matrix->triv_idx); free(matrix->triv_pos); free(matrix->dst); free(matrix); free(len_gb_xn); free(start_cf_gb_xn); free(div_xn); return NULL; } } else{ if(info_level){ fprintf(stderr, "Staircase is not generic\n"); fprintf(stderr, "Multiplication by "); display_monomial_full(stderr, nv, NULL, 0, exp); fprintf(stderr, " gets outside the staircase\n"); } free(matrix->dense_mat); free(matrix->dense_idx); free(matrix->triv_idx); free(matrix->triv_pos); free(matrix->dst); free(matrix); free(len_gb_xn); free(start_cf_gb_xn); free(div_xn); return NULL; } } } for(long i = 0; i < matrix->nrows; i++){ for(long j = matrix->ncols - 1; j >= 0; j--){ if(matrix->dense_mat[i*matrix->ncols + j] == 0){ matrix->dst[i]++; } else{ break; } } } return matrix; } #undef REDUCTION_ALLINONE static inline int32_t *get_lm_from_bs(const bs_t * const bs, const ht_t * const ht){ hm_t *dt; const len_t nelts = bs->lml; const int nv = ht->nv; const len_t ebl = ht->ebl; const len_t evl = ht->evl; int32_t *exp = (int32_t *)malloc( (unsigned long)(nelts) * (unsigned long)(nv) * sizeof(int32_t)); /* counters for lengths, exponents and coefficients */ int64_t cl = 0, ce = 0;//, cc = 0, ctmp = 0;; for (long i = 0; i < nelts; ++i) { const bl_t bi = bs->lmps[i]; dt = bs->hm[bi] + OFFSET; for (int k = 1; k < ebl; ++k) { exp[ce++] = (int32_t)ht->ev[dt[0]][k]; } for (int k = ebl+1; k < evl; ++k) { exp[ce++] = (int32_t)ht->ev[dt[0]][k]; } cl++; } return exp; } static inline void get_lm_from_bs_trace(bs_t *bs, const ht_t *ht, int32_t *exp){ hm_t *dt; const len_t nelts = bs->lml; const len_t ebl = ht->ebl; const len_t evl = ht->evl; /* counters for lengths, exponents and coefficients */ int64_t cl = 0, ce = 0;//, cc = 0, ctmp = 0;; for (long i = 0; i < nelts; ++i) { const bl_t bi = bs->lmps[i]; // len[cl] = bs->hm[bi][LENGTH]; dt = bs->hm[bi] + OFFSET; for (int k = 1; k < ebl; ++k) { exp[ce++] = (int32_t)ht->ev[dt[0]][k]; } for (int k = ebl+1; k < evl; ++k) { exp[ce++] = (int32_t)ht->ev[dt[0]][k]; } // cc += len[cl]; cl++; } } static inline void get_lm_from_bs_trace_elim(bs_t *bs, const ht_t *ht, int32_t *exp, const len_t nelts){ hm_t *dt; const len_t ebl = ht->ebl; const len_t evl = ht->evl; /* counters for lengths, exponents and coefficients */ int64_t cl = 0, ce = 0;//, cc = 0, ctmp = 0;; for (long i = 0; i < nelts; ++i) { const bl_t bi = bs->lmps[i]; // len[cl] = bs->hm[bi][LENGTH]; dt = bs->hm[bi] + OFFSET; /* for (int k = 1; k < ebl; ++k) { */ /* exp[ce++] = (int32_t)ht->ev[dt[0]][k]; */ /* } */ for (int k = ebl+1; k < evl; ++k) { exp[ce++] = (int32_t)ht->ev[dt[0]][k]; } // cc += len[cl]; cl++; } } static inline int equal_staircase(int32_t *lmb, int32_t *lmb_ori, long dquot, long dquot_ori, int32_t nv){ if(dquot != dquot_ori){ return 0; } for(long i = 0; i < dquot; i++){ for(int32_t j = 0; j < nv; j++){ if(lmb[i*nv+j] != lmb_ori[i*nv+j]){ return 0; } } } return 1; } msolve-0.6.5/src/msolve/iofiles.c000066400000000000000000001011121456710632100167220ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ static inline void store_exponent(const char *term, data_gens_ff_t *gens, int32_t pos) { len_t i, j, k; len_t op = 0; char *var = NULL; char *ev = NULL; for (i = 0; i < strlen(term)+1; ++i) { if (term[i] == '*' || i == strlen(term)) { j = op; while (j < i && term[j] != '^') { ++j; } if (term[j-1] == ',') { --j; } while(term[op] == ' ' || term[op] == '+' || term[op] == '-') { ++op; } var = realloc(var, sizeof(char)*(j-op+1)); memcpy(var, term+op, j-op); var[j-op] = '\0'; if (term[j] == '^') { ev = realloc(ev, (sizeof(char)*(i-j))); ev = memcpy(ev, term+(j+1), i-j-1); ev[i-j-1] = '\0'; } else { ev = realloc(ev, (sizeof(char)*2)); ev[0] = '1'; ev[1] ='\0'; } for (k = 0; k < gens->nvars; ++k) { if (strcmp(gens->vnames[k], var) == 0) { ((gens->exps) + pos)[k] = strtol(ev, NULL, 10); break; } } op = i+1; } } free(var); free(ev); } static inline void display_monomial(FILE *file, data_gens_ff_t *gens, int64_t pos, int32_t **bexp){ int32_t exp = 0; for(int k = 0; k < gens->nvars - gens->elim; k++){ exp = (*bexp)[(pos)*(gens->nvars - gens->elim) + k]; if(exp > 0){ break; } } if(exp == 0){ fprintf(file, "1"); return; } for(int k = 0; k < (gens->nvars - gens->elim); k++){ exp = (*bexp)[(pos)*(gens->nvars - gens->elim) + k]; if(exp > 0){ fprintf(file, "*"); if(exp==1){ fprintf(file, "%s", gens->vnames[k + gens->elim]); } else{ fprintf(file, "%s^%d",gens->vnames[k + gens->elim], exp); } } } } static inline int32_t display_monomial_single(FILE *file, data_gens_ff_t *gens, int64_t pos, int32_t **bexp){ int32_t exp, b = 0; for(int k = 0; k < gens->nvars - gens->elim; k++){ exp = (*bexp)[(pos)*(gens->nvars - gens->elim) + k]; if(exp > 0){ if(exp==1){ if(b){ fprintf(file, "*%s", gens->vnames[k + gens->elim]); } else{ fprintf(file, "%s", gens->vnames[k + gens->elim]); } } else{ if(b){ fprintf(file, "*%s^%d",gens->vnames[k + gens->elim], exp); } else{ fprintf(file, "%s^%d",gens->vnames[k + gens->elim], exp); } } b = 1; } } return b; } static inline int32_t display_monomial_full(FILE *file, const int nv, char **vnames, int64_t pos, int32_t *bexp){ int32_t exp, b = 0; for(int k = 0; k < nv; k++){ exp = (bexp)[(pos)*nv + k]; if(exp > 0){ if(exp==1){ if(b){ // fprintf(file, "*%s", vnames[k]); fprintf(file, "*x%d", k+1); } else{ // fprintf(file, "%s", vnames[k]); fprintf(file, "x%d", k+1); } } else{ if(b){ fprintf(file, "*x%d^%d",k+1, exp); } else{ fprintf(file, "x%d^%d",k+1, exp); } } b = 1; } } if(b==0){ fprintf(file, "1"); } return b; } static void print_msolve_polynomials_ff( FILE *file, const bi_t from, const bi_t to, const bs_t * const bs, const ht_t * const ht, const md_t *st, char **vnames, const int lead_ideal_only, const int is_nf ) { len_t i, j, k, idx; len_t len = 0; hm_t *hm = NULL; const len_t nv = ht->nv; const len_t ebl = ht->ebl; const len_t evl = ht->evl; /* state context if full basis is printed */ if (is_nf == 0 && from == 0 && to == bs->lml) { if (lead_ideal_only != 0) { fprintf(file, "#Leading ideal data\n"); } else { fprintf(file, "#Reduced Groebner basis data\n"); } fprintf(file, "#---\n"); fprintf(file, "#field characteristic: %u\n", st->gfc); fprintf(file, "#variable order: "); for (i = 0; i < nv-1; ++i) { fprintf(file, "%s, ", vnames[i]); } fprintf(file, "%s\n", vnames[nv-1]); if (st->nev == 0) { fprintf(file, "#monomial order: graded reverse lexicographical\n"); } else { if (st->nev == 1) { fprintf(file, "#monomial order: eliminating first variable, blocks: graded reverse lexicographical\n"); } else { fprintf(file, "#monomial order: eliminating first %d variables, blocks: graded reverse lexicographical\n", st->nev); } } if (bs->lml == 1) { fprintf(file, "#length of basis: 1 element\n"); } else { fprintf(file, "#length of basis: %u elements sorted by increasing leading monomials\n", bs->lml); } fprintf(file, "#---\n"); } int *evi = (int *)malloc((unsigned long)ht->nv * sizeof(int)); if (ebl == 0) { for (i = 1; i < evl; ++i) { evi[i-1] = i; } } else { for (i = 1; i < ebl; ++i) { evi[i-1] = i; } for (i = ebl+1; i < evl; ++i) { evi[i-2] = i; } } if (lead_ideal_only != 0) { int ctr = 0; fprintf(file, "["); for (i = from; i < to; ++i) { idx = bs->lmps[i]; if (bs->hm[idx] == NULL) { fprintf(file, "0,\n"); } else { hm = bs->hm[idx]+OFFSET; len = bs->hm[idx][LENGTH]; ctr = 0; k = 0; while (ctr == 0 && k < nv) { if (ht->ev[hm[0]][evi[k]] > 0) { fprintf(file, "%s^%u",vnames[k], ht->ev[hm[0]][evi[k]]); ctr++; } k++; } for (;k < nv; ++k) { if (ht->ev[hm[0]][evi[k]] > 0) { fprintf(file, "*%s^%u",vnames[k], ht->ev[hm[0]][evi[k]]); } } if (i < to-1) { fprintf(file, ",\n"); } else { fprintf(file, "]:\n"); } } } } else { fprintf(file, "["); for (i = from; i < to; ++i) { idx = bs->lmps[i]; if (bs->hm[idx] == NULL) { fprintf(file, "0,\n"); } else { hm = bs->hm[idx]+OFFSET; len = bs->hm[idx][LENGTH]; switch (st->ff_bits) { case 0 : fprintf(file, "%u", bs->cf_32[bs->hm[idx][COEFFS]][0]); break; case 8: fprintf(file, "%u", bs->cf_8[bs->hm[idx][COEFFS]][0]); break; case 16: fprintf(file, "%u", bs->cf_16[bs->hm[idx][COEFFS]][0]); break; case 32: fprintf(file, "%u", bs->cf_32[bs->hm[idx][COEFFS]][0]); break; } for (k = 0; k < nv; ++k) { if (ht->ev[hm[0]][evi[k]] > 0) { fprintf(file, "*%s^%u",vnames[k], ht->ev[hm[0]][evi[k]]); } } for (j = 1; j < len; ++j) { switch (st->ff_bits) { case 0: fprintf(file, "+%u", bs->cf_32[bs->hm[idx][COEFFS]][j]); break; case 8: fprintf(file, "+%u", bs->cf_8[bs->hm[idx][COEFFS]][j]); break; case 16: fprintf(file, "+%u", bs->cf_16[bs->hm[idx][COEFFS]][j]); break; case 32: fprintf(file, "+%u", bs->cf_32[bs->hm[idx][COEFFS]][j]); break; } for (k = 0; k < nv; ++k) { if (ht->ev[hm[j]][evi[k]] > 0) { fprintf(file, "*%s^%u",vnames[k], ht->ev[hm[j]][evi[k]]); } } } if (i < to-1) { fprintf(file, ",\n"); } else { fprintf(file, "]:\n"); } } } } free(evi); } static void print_ff_nf_data( const char *fn, const char *mode, const bi_t from, const bi_t to, const bs_t *bs, const ht_t *ht, const md_t *st, const data_gens_ff_t *gens, const int32_t print_gb) { if (print_gb > 0) { if(fn != NULL){ FILE *ofile = fopen(fn, mode); print_msolve_polynomials_ff(ofile, from, to, bs, ht, st, gens->vnames, 2-print_gb, 1); fclose(ofile); } else{ print_msolve_polynomials_ff(stdout, from, to, bs, ht, st, gens->vnames, 2-print_gb, 1); } } } static void print_ff_basis_data( const char *fn, const char *mode, const bs_t *bs, const ht_t *ht, const md_t *st, const data_gens_ff_t *gens, const int32_t print_gb) { if (print_gb > 0) { if(fn != NULL){ FILE *ofile = fopen(fn, mode); print_msolve_polynomials_ff(ofile, 0, bs->lml, bs, ht, st, gens->vnames, 2-print_gb, 0); fclose(ofile); } else{ print_msolve_polynomials_ff(stdout, 0, bs->lml, bs, ht, st, gens->vnames, 2-print_gb, 0); } } } static int32_t get_nvars(const char *fn) { FILE *fh = fopen(fn,"r"); /** load lines and store data */ const int max_line_size = 1073741824; char *line = (char *)malloc((nelts_t)max_line_size * sizeof(char)); /** get first line (variables) */ const char comma_splicer = ','; /** get number of variables */ nvars_t nvars = 1; /** number of variables is number of commata + 1 in first line */ if (fgets(line, max_line_size, fh) != NULL) { char *tmp = strchr(line, comma_splicer); while (tmp != NULL) { /** if there is a comma at the end of the line, i.e. strlen(line)-2 (since * we have "\0" at the end of the string line, then we do not get another * variable */ if ((uint32_t)(tmp-line) < strlen(line)-2) { nvars++; tmp = strchr(tmp+1, comma_splicer); } else { break; } } } else { printf("Bad file format.\n"); nvars = 0; } free(line); fclose(fh); return nvars; } /** * Checks is a line of the input file is just empty resp. consists only * of whitespaces * * \param line line * * \return 1 if the line is empty, else 0 */ static inline int is_line_empty(const char *line) { while (*line != '\0') { if (!isspace(*line)) return 0; line++; } return 1; } static int32_t get_ngenerators(char *fn){ int32_t nlines = 0; char *line = NULL; size_t len = 0; FILE *fh = fopen(fn,"r"); /* first line are the variables */ if (getline(&line, &len, fh) == -1) { fclose(fh); return -1; } /* second line is the characteristic */ if (getline(&line, &len, fh) == -1) { fclose(fh); return -1; } while(getdelim(&line, &len, ',', fh) != -1) { /* check if there are empty lines in the input file */ if (is_line_empty(line) == 0) nlines++; } free(line); fclose(fh); return nlines; } static inline char *get_variable_name(const char *line, char **prev_pos) { const char comma_splicer = ','; char *tmp_var = (char *)malloc(50 * sizeof(char)); char *curr_pos = strchr(*prev_pos, comma_splicer); if (curr_pos != NULL) { size_t var_diff = (size_t)(curr_pos - *prev_pos); memcpy(tmp_var, *prev_pos, var_diff); tmp_var[var_diff] = '\0'; *prev_pos = curr_pos+1; } else { /** we are at the last variable */ int prev_idx = (int)(*prev_pos - line); int curr_idx = (int)(strlen(line)+1); size_t var_diff = (size_t)(curr_idx - prev_idx); memcpy(tmp_var, *prev_pos, var_diff); tmp_var[var_diff] = '\0'; } /** trim variable, remove blank spaces */ char *tmp_var_begin, *tmp_var_end; tmp_var_begin = tmp_var_end = tmp_var; while (isspace(*tmp_var_begin)) tmp_var_begin++; if (*tmp_var_begin != 0) { while (*tmp_var_end) tmp_var_end++; do { tmp_var_end--; } while (isspace(*tmp_var_end)); } int fin_len = (int)(tmp_var_end - tmp_var_begin + 1); size_t final_length = 0; if (fin_len > 0) final_length = (size_t)fin_len; char *final_var = (char *)malloc((final_length+1) * sizeof(char)); memcpy(final_var, tmp_var_begin, final_length); final_var[final_length] = '\0'; free(tmp_var); return final_var; } static inline nelts_t get_number_of_terms(const char *line) { const char add_splicer = '+'; const char minus_splicer = '-'; const char whitespace_splicer = ' '; char *tmp = NULL; nelts_t nterms = 1; /** remove useless whitespaces at the beginning */ int i = 0; while (strncmp(&whitespace_splicer, line+i, 1) == 0) i++; /** check if first non-whitespace char is "-", set term counter -1 in this case */ if (strncmp(&minus_splicer, line+i, 1) == 0) nterms--; /** now count terms */ tmp = strchr(line, add_splicer); while (tmp != NULL) { nterms++; tmp = strchr(tmp+1, add_splicer); } tmp = strchr(line, minus_splicer); while (tmp != NULL) { nterms++; tmp = strchr(tmp+1, minus_splicer); } //MS que faire si dans la ligne on a 0*x+0*y ? return nterms; } static void get_variables(FILE *fh, char * line, int max_line_size, int32_t *nr_vars, data_gens_ff_t *gens, char **vnames){ long i; char *tmp = NULL; if (fgets(line, max_line_size, fh) != NULL) { tmp = line; } else { printf("Bad file format (variable names).\n"); /* free(vnames); * free(line); */ fclose(fh); exit(1); } for (i=0; i<(*nr_vars); ++i) { vnames[i] = get_variable_name(line, &tmp); } gens->vnames = vnames; } static void get_characteristic(FILE *fh, char * line, int max_line_size, int32_t *field_char, char **vnames){ *field_char = 0; if(fgets(line, max_line_size, fh) != NULL){ int64_t tmp_mod = atol(line); if(tmp_mod >= 0){ *field_char = (int32_t) tmp_mod; if(tmp_mod > 2147483647){ fprintf(stderr, "Warning: characteristic must be 0 or < 2^31\n"); free(vnames); free(line); fclose(fh); exit(1); } } else{ fprintf(stderr, "Bad file format (characteristic)\n"); free(vnames); free(line); fclose(fh); exit(1); } } } static void get_nterms_and_all_nterms(FILE *fh, char **linep, int max_line_size, data_gens_ff_t *gens, int32_t *nr_gens, nelts_t *nterms, nelts_t *all_nterms){ char *line = *linep; int32_t i = 0, j = 0, k = 0; size_t len = 0; while(getdelim(&line, &len, ',', fh) != -1) { for (k = 0, j = 0; j < len; ++j) { if (line[j] != '\n' && line[j] != ' ') { line[k++] = line[j]; } } *nterms = get_number_of_terms(line); gens->lens[i] = *nterms; *all_nterms += *nterms; len = 0; i++; } *linep = line; gens->nterms = *all_nterms; } static inline void get_term(const char *line, char **prev_pos, char **term, size_t *term_size) { /** note that maximal term length we handle */ const char add_splicer = '+'; const char minus_splicer = '-'; char *start_pos; char *curr_pos_add = strchr(*prev_pos, add_splicer); char *curr_pos_minus = strchr(*prev_pos, minus_splicer); if (curr_pos_minus == line) curr_pos_minus = strchr(*prev_pos+1, minus_splicer); if (*prev_pos != line) start_pos = *prev_pos - 1; else start_pos = *prev_pos; if (curr_pos_add != NULL && curr_pos_minus != NULL) { size_t term_diff_add = (size_t)(curr_pos_add - start_pos); size_t term_diff_minus = (size_t)(curr_pos_minus - start_pos); /** if "-" is the first char in the line, we have to adjust the * if minus is nearer */ if (term_diff_add > term_diff_minus) { if( term_diff_minus > *term_size){ fprintf(stderr, "Too large input integers, exit...\n"); exit(1); } memcpy(*term, start_pos, term_diff_minus); (*term)[term_diff_minus] = '\0'; *prev_pos = curr_pos_minus+1; return; /** if plus is nearer */ } else { if(term_diff_add > *term_size){ fprintf(stderr, "Too large input integers, exit...\n"); exit(1); } memcpy(*term, start_pos, term_diff_add); (*term)[term_diff_add] = '\0'; *prev_pos = curr_pos_add+1; return; } } else { if (curr_pos_add != NULL) { size_t term_diff_add = (size_t)(curr_pos_add - start_pos); if(term_diff_add > *term_size){ fprintf(stderr, "Too large input integers, exit...\n"); exit(1); } memcpy(*term, start_pos, term_diff_add); (*term)[term_diff_add] = '\0'; *prev_pos = curr_pos_add+1; return; } if (curr_pos_minus != NULL) { size_t term_diff_minus = (size_t)(curr_pos_minus - start_pos); if(term_diff_minus > *term_size){ fprintf(stderr, "Too large input integers, exit...\n"); exit(1); } memcpy(*term, start_pos, term_diff_minus); (*term)[term_diff_minus] = '\0'; *prev_pos = curr_pos_minus+1; return; } if (curr_pos_add == NULL && curr_pos_minus == NULL) { size_t prev_idx = (size_t)(start_pos - line); size_t term_diff = strlen(line) + 1 - prev_idx; if(term_diff > *term_size){ fprintf(stderr, "Too large input integers, exit...\n"); exit(1); } memcpy(*term, start_pos, term_diff); (*term)[term_diff] = '\0'; return; } } } /*assumes that coeffs in file fit in word size */ static int get_coefficient_ff_and_term_from_line(char *line, int32_t nterms, int32_t field_char, data_gens_ff_t *gens, int32_t pos){ char *prev_pos = NULL; size_t term_size = 50000; char *term = (char *)malloc(term_size * sizeof(char)); long int cf_tmp = 0; /** temp for coefficient value, possibly coeff is negative. */ prev_pos = line; get_term(line, &prev_pos, &term, &term_size); if(term != NULL){ int32_t iv_tmp = (int32_t)strtol(term, NULL, 10); if (iv_tmp == 0) { switch (term[0]) { case '0': iv_tmp = 0; break; case '-': iv_tmp = -1; break; default: iv_tmp = 1; break; } } while (iv_tmp < 0) { iv_tmp += (int32_t)field_char; //MS change int -> long int } gens->cfs[pos] = (int32_t)iv_tmp; store_exponent(term, gens, pos*gens->nvars); for(int j = 1; j < nterms; j++){ get_term(line, &prev_pos, &term, &term_size); if (term != NULL) { cf_tmp = (int)strtol(term, NULL, 10); if (cf_tmp == 0) { if (term[0] == '-') { cf_tmp = -1; } else { cf_tmp = 1; } } while (cf_tmp < 0) { cf_tmp += (int)field_char; } gens->cfs[pos+j] = cf_tmp; store_exponent(term, gens, (pos+j)*gens->nvars); } // store_exponent(term, basis, ht); } free(term); return 0; } free(term); return 1; } static void beginning_strterm_to_mpz(char *str, mpz_t *num, mpz_t *den){ /* fprintf(stderr, "TERM = %s\n", str); */ mpq_t tmp; mpq_init(tmp); mpz_set_ui(*num, 1); mpz_set_ui(*den, 1); size_t m = 0; size_t len = strlen(str); for(m = 0; m < len; m++){ if(str[m]=='*' || str[m]==',') break; } const size_t sz = m; char *buf = (char *)malloc((sz+1) * sizeof(char)); for(long i = 0; i < sz; i++){ buf[i]=str[i]; } buf[sz]='\0'; int b = mpq_set_str(tmp, buf, 10); mpq_get_num(*num, tmp); mpq_get_den(*den, tmp); if(b!=0) { if (buf[0] == '-') { mpz_set_si(*num, -1); mpz_set_si(*den, 1); } else { mpz_set_si(*num, 1); mpz_set_si(*den, 1); } } free(buf); mpq_clear(tmp); } static void inner_strterm_to_mpz(char *str, mpz_t *num, mpz_t *den){ mpq_t tmp; mpq_init(tmp); mpz_set_ui(*num, 1); mpz_set_ui(*den, 1); size_t m = 0; size_t len = strlen(str); for(m = 0; m < len; m++){ if(str[m]=='*' || str[m]==',') break; } const size_t sz = m; char *buf = (char *)malloc((sz+1) * sizeof(char)); for(long i = 1; i < sz; i++){ buf[i-1]=str[i]; } buf[sz-1]='\0'; int b = mpq_set_str(tmp, buf, 10); mpq_get_num(*num, tmp); mpq_get_den(*den, tmp); if(b!=0) { mpz_set_si(*num, 1); mpz_set_si(*den, 1); } if(str[0]=='-'){ mpz_neg(*num, *num); } free(buf); mpq_clear(tmp); } static int get_coefficient_mpz_and_term_from_line(char *line, int32_t nterms, int32_t field_char, data_gens_ff_t *gens, int32_t pos){ char *prev_pos = NULL; size_t term_size = 50000; char *term = (char *)malloc(term_size * sizeof(char)); prev_pos = line; get_term(line, &prev_pos, &term, &term_size); if(term != NULL){ beginning_strterm_to_mpz(term, gens->mpz_cfs[pos], gens->mpz_cfs[pos+1]); store_exponent(term, gens, pos/2*gens->nvars); for(int j = 2; j < 2*nterms; j+=2){ get_term(line, &prev_pos, &term, &term_size); inner_strterm_to_mpz(term, gens->mpz_cfs[pos+j], gens->mpz_cfs[pos+j+1]); store_exponent(term, gens, ((pos+j)/2)*gens->nvars); } free(term); return 0; } free(term); return 1; } static void get_coeffs_and_exponents_ff32(FILE *fh, char **linep, nelts_t all_nterms, int32_t *nr_gens, data_gens_ff_t *gens){ int32_t pos = 0; size_t len = 0; char *line = *linep; if(getline(&line, &len, fh) !=-1){ } if(getline(&line, &len, fh) !=-1){ } gens->cfs = (int32_t *)(malloc(sizeof(int32_t) * all_nterms)); gens->exps = (int32_t *)calloc(all_nterms * gens->nvars, sizeof(int32_t)); long i, j, k; for(i = 0; i < *nr_gens; i++){ if (getdelim(&line, &len, ',', fh) != -1) { for (k = 0, j = 0; j < len; ++j) { if (line[j] != '\n' && line[j] != ' ') { line[k++] = line[j]; } } if (line[k-1] == ',') { line[k-1] = '\0'; } } if(get_coefficient_ff_and_term_from_line(line, gens->lens[i], gens->field_char, gens, pos)){ fprintf(stderr, "Error when reading file (exit but things need to be free-ed)\n"); free(line); fclose(fh); exit(1); } pos += gens->lens[i]; } *linep = line; } static void get_coeffs_and_exponents_mpz(FILE *fh, char **linep, nelts_t all_nterms, int32_t *nr_gens, data_gens_ff_t *gens){ int32_t pos = 0; size_t len = 0; char *line = *linep; if(getline(&line, &len, fh) !=-1){ } if(getline(&line, &len, fh) !=-1){ } gens->cfs = (int32_t*)(malloc(sizeof(int32_t) * all_nterms)); gens->mpz_cfs = (mpz_t **)(malloc(sizeof(mpz_t *) * 2 * all_nterms)); for(long i = 0; i < 2 * all_nterms; i++){ gens->mpz_cfs[i] = (mpz_t *)malloc(sizeof(mpz_t)); mpz_init(*(gens->mpz_cfs[i])); } gens->exps = (int32_t *)calloc(all_nterms * gens->nvars, sizeof(int32_t)); long i, j, k; for(i = 0; i < *nr_gens; i++){ if (getdelim(&line, &len, ',', fh) != -1) { for (k = 0, j = 0; j < len; ++j) { if (line[j] != '\n' && line[j] != ' ') { line[k++] = line[j]; } } if (line[k-1] == ',') { line[k-1] = '\0'; } } if(get_coefficient_mpz_and_term_from_line(line, gens->lens[i], gens->field_char, gens, pos)){ fprintf(stderr, "Error when reading file (exit but things need to be free-ed)\n"); free(line); fclose(fh); exit(1); } pos += 2 * gens->lens[i]; } *linep = line; } static inline void initialize_data_gens(int32_t nvars, int32_t ngens, int32_t field_char, data_gens_ff_t *gens){ gens->nvars = nvars; gens->ngens = ngens; gens->field_char = field_char; gens->change_var_order = -1; gens->linear_form_base_coef = 0; gens->rand_linear = 0; gens->lens = (int32_t *)malloc(sizeof(int32_t) * ngens); } static int duplicate_vnames(char **vnames, int32_t nvars) { int32_t i, j; for (i = 1; i < nvars; ++i) { for (j = 0; j < i; ++j) { if (strcmp(vnames[i], vnames[j]) == 0) { fprintf(stderr, "Duplicate variable name %s in input file.\n", vnames[i]); return 1; } } } return 0; } //nr_gens is a pointer to the number of generators static inline void get_data_from_file(char *fn, int32_t *nr_vars, int32_t *field_char, int32_t *nr_gens, data_gens_ff_t *gens){ *nr_vars = get_nvars(fn); *nr_gens = get_ngenerators(fn); const int max_line_size = 1073741824; char *line = (char *)calloc((nelts_t)max_line_size, sizeof(char)); FILE *fh = fopen(fn,"r"); /** allocate memory for storing variable names */ char **vnames = (char **)malloc((*nr_vars) * sizeof(char *)); get_variables(fh, line, max_line_size, nr_vars, gens, vnames); if (duplicate_vnames(vnames, *nr_vars) == 1) { free(vnames); free(line); exit(1); } get_characteristic(fh, line, max_line_size, field_char, vnames); initialize_data_gens(*nr_vars, *nr_gens, *field_char, gens); nelts_t nterms, all_nterms = 0; get_nterms_and_all_nterms(fh, &line, max_line_size, gens, nr_gens, &nterms, &all_nterms); fclose(fh); fh = fopen(fn, "r"); if(gens->field_char){ get_coeffs_and_exponents_ff32(fh, &line, all_nterms, nr_gens, gens); } else{ get_coeffs_and_exponents_mpz(fh, &line, all_nterms, nr_gens, gens); } free(line); fclose(fh); return; } static inline void display_gens_ff(FILE *fh, data_gens_ff_t *gens){ long pos = 0; int c; for(long i = 0; i < gens->ngens; i++){ for(long j = 0; j < gens->lens[i]-1; j++){ c = gens->cfs[pos+j]; if(c != 1){ fprintf(fh, "%d", c); display_monomial(fh, gens, pos+j, &gens->exps); } else{ display_monomial_single(fh, gens, pos+j, &gens->exps); } fprintf(fh, "+"); } c = gens->cfs[pos+gens->lens[i]-1]; if(c!= 1){ fprintf(fh, "%d", c); display_monomial(fh, gens, pos+gens->lens[i]-1, &gens->exps); } else{ int b = display_monomial_single(fh, gens, pos+gens->lens[i]-1, &gens->exps); if(b==0){ fprintf(fh, "1"); } } pos+=gens->lens[i]; if(i < gens->ngens-1){ fprintf(fh,",\n"); } else{ fprintf(fh,"\n"); } } } static void display_gens_mpz(FILE *fh, data_gens_ff_t *gens){ long pos = 0, posex = 0; for(long i = 0; i < gens->ngens; i++){ for(long j = 0; j < gens->lens[i]-1; j++){ if(mpz_cmp_ui(*(gens->mpz_cfs[pos+2*j]), 1) != 0){ mpz_out_str(fh, 10, *(gens->mpz_cfs[pos+2*j])); display_monomial(fh, gens, posex+j, &gens->exps); } else{ display_monomial_single(fh, gens, posex+j, &gens->exps); } if(mpz_cmp_ui(*(gens->mpz_cfs[pos+2*(j+1)]), 0) > 0){ fprintf(fh, "+"); } } if(mpz_cmp_ui(*(gens->mpz_cfs[pos+ 2*(gens->lens[i] -1)]), 1) != 0){ mpz_out_str(fh, 10, *(gens->mpz_cfs[pos+2*(gens->lens[i]-1)])); display_monomial(fh, gens, posex+(gens->lens[i]-1), &gens->exps); } else{ int b = display_monomial_single(fh, gens, posex+gens->lens[i]-1, &gens->exps); if(b==0){ fprintf(fh, "1"); } } pos+=2*gens->lens[i]; posex+=gens->lens[i]; if(i < gens->ngens-1){ fprintf(fh,",\n"); } else{ fprintf(fh,"\n"); } } } static inline void display_gens(FILE *fh, data_gens_ff_t *gens){ for(int i = 0; i < gens->nvars-1; i++){ fprintf(fh, "%s, ", gens->vnames[i]); } fprintf(fh, "%s\n", gens->vnames[gens->nvars-1]); fprintf(fh, "%d\n", gens->field_char); if(gens->field_char > 0){ display_gens_ff(fh, gens); } else{ display_gens_mpz(fh, gens); } } static inline void get_poly_bin(FILE *file, mpz_upoly_t pol){ if(!fscanf(file, "%d\n", &pol->alloc)){ fprintf(stderr, "Issue when reading binary file (alloc = %d)\n", pol->alloc); exit(1); } pol->coeffs = malloc(sizeof(mpz_t) * pol->alloc); pol->length = pol->alloc; for(int32_t i = 0; i < pol->length; i++){ mpz_init(pol->coeffs[i]); if(!mpz_inp_raw(pol->coeffs[i], file)){ fprintf(stderr, "An error occurred when reading file (i=%d)\n", i); exit(1); } } } static inline void get_poly(FILE *file, mpz_upoly_t pol){ if(!fscanf(file, "%d\n", &pol->alloc)){ fprintf(stderr, "Issue when reading binary file (alloc = %d)\n", pol->alloc); exit(1); } pol->coeffs = malloc(sizeof(mpz_t) * pol->alloc); pol->length = pol->alloc; for(int32_t i = 0; i < pol->length; i++){ mpz_init(pol->coeffs[i]); if(!mpz_inp_str(pol->coeffs[i], file, 10)){ fprintf(stderr, "An error occurred when reading file (i=%d)\n", i); exit(1); } } } static inline void get_single_param_from_file_bin(FILE *file, mpz_param_t param){ get_poly_bin(file, param->elim); get_poly_bin(file, param->denom); if(!fscanf(file, "%d\n", ¶m->nvars)){ fprintf(stderr, "Issue when reading binary file (nvars)\n"); exit(1); } param->nsols = param->elim->length - 1; param->dquot = param->elim->length - 1; param->coords = malloc(sizeof(mpz_upoly_t) * param->nvars); param->cfs = malloc(sizeof(mpz_t) * param->nvars); for(int32_t i = 0; i < param->nvars - 1; i++){ get_poly_bin(file, param->coords[i]); mpz_init(param->cfs[i]); if(!mpz_inp_raw(param->cfs[i], file)){ fprintf(stderr, "An error occurred when reading file (lcm coord i=%d)\n", i); exit(1); } } } static inline void get_single_param_from_file(FILE *file, mpz_param_t param){ get_poly(file, param->elim); get_poly(file, param->denom); if(!fscanf(file, "%d\n", ¶m->nvars)){ fprintf(stderr, "Issue when reading binary file (nvars)\n"); exit(1); } param->nsols = param->elim->length - 1; param->dquot = param->elim->length - 1; param->coords = malloc(sizeof(mpz_upoly_t) * param->nvars); param->cfs = malloc(sizeof(mpz_t) * param->nvars); for(int32_t i = 0; i < param->nvars - 1; i++){ get_poly(file, param->coords[i]); mpz_init(param->cfs[i]); if(!mpz_inp_str(param->cfs[i], file, 10)){ fprintf(stderr, "An error occurred when reading file (i=%d)\n", i); exit(1); } } } static inline void get_params_from_file_bin(char *fn, mpz_param_array_t lparam){ FILE *file = fopen(fn,"r"); int32_t nb = 0; if(!fscanf(file, "%d\n", &nb)){ fprintf(stderr, "Issue when reading binary file (nb = %d)\n", nb); exit(1); } lparam->nb = nb; lparam->params = malloc(sizeof(mpz_param_t) * lparam->nb); for(int32_t i = 0; i < lparam->nb; i++){ get_single_param_from_file_bin(file, lparam->params[i]); } fclose(file); } static inline void get_params_from_file(char *fn, mpz_param_array_t lparam){ FILE *file = fopen(fn,"r"); int32_t nb = 0; if(!fscanf(file, "%d\n", &nb)){ fprintf(stderr, "Issue when reading binary file (nb = %d)\n", nb); exit(1); } lparam->nb = nb; lparam->params = malloc(sizeof(mpz_param_t) * lparam->nb); for(int32_t i = 0; i < lparam->nb; i++){ get_single_param_from_file(file, lparam->params[i]); } fclose(file); } msolve-0.6.5/src/msolve/libmsolve.c000066400000000000000000000021011456710632100172620ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #if HAVE_CONFIG_H #include "config.h" #endif #include "msolve-data.h" #include "msolve-data.c" #include "iofiles.c" #include "hilbert.c" #include "primes.c" #include "../crt/mpz_CRT_ui.c" #include "../crt/mpq_reconstruct.c" #include "../usolve/data_usolve.c" #include "../usolve/libusolve.h" #include "../neogb/libneogb.h" #include "msolve.c" msolve-0.6.5/src/msolve/lifting-gb.c000066400000000000000000001372251456710632100173300ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include #define NBCHECK 2 #ifndef MIN #define MIN(x, y) ((x) > (y) ? (y) : (x)) #endif #ifndef MAX #define MAX(a,b) (((a)>(b))?(a):(b)) #endif typedef struct{ uint32_t len; /* length of the encoded polynomial */ uint32_t **cf_32; /* array of arrays of coefficients * modulo several primes */ mpz_t *cf_zz; /* array which stores CRT lifting of the coefficiels */ mpz_t *cf_qq; /* array which stores rational coefficients being lifted, numerators and denominators are given given as mpz_t */ mpz_t lm; /* stores the leading coefficient (hence all numerators of cf_qq should be divided by lm) */ } modpolys_struct; typedef modpolys_struct modpolys_t[1]; typedef struct { uint32_t alloc; /* alloc -> max number of primes */ uint32_t nprimes; /* number of primes */ uint64_t *primes; /* array of prime numbers encoded with uint64_t to ensure compatibility with flint */ uint64_t *cf_64; /* array of length equal to number of primes which will be used to copy coefficients (hence ensuring compatibility with flint) */ uint32_t ld; /* number of polynomials */ int nv; /* number of variables */ int32_t *mb; /* monomial basis enlarged */ int32_t *ldm; /* lead monomials */ modpolys_t *modpolys; /* array of polynomials modulo primes */ } gb_modpoly_array_struct; typedef gb_modpoly_array_struct gb_modpoly_t[1]; #define NEWGBLIFT 1 typedef struct{ int32_t npol; /* number of polynomials to be lifted */ int32_t rr; /* number of primes before activating rational reconstruction */ int32_t nsteps; /* number of steps for lifting GB (per degree) */ int32_t *steps; /* array of length nsteps ; the sum of the entries should equal npol */ int32_t cstep; /* current step lifting GB */ /* liftings are performed on ranges of polynomials (depending on their degrees) */ int32_t lstart; /* index of first polynomial to be lifted */ int32_t lend; /* index of last polynomial to be lifted */ int crt_mult; /* indicates if multi-mod flint structures need to be initialized */ mpz_t *crt; /* stores current CRT */ int recon; /* equals 1 when some rational number can be lifted, else 0 */ int32_t *coef; /* array of indices to lift */ mpz_t *num; /* lifted numerator */ mpz_t *den; /* lifted denominator */ mpz_t gden; /* guessed denominator */ mpz_t tmp; int32_t start; /* smallest index of poly whose witness coef has been lifted but not checked*/ int32_t end; /* largest index of poly whose witness coef has been lifted but not checked*/ int *check1; /* tells whether lifted data are ok with one more prime */ int *check2; /* tells whether lifted data are ok with two more primes */ int32_t S; } data_lift_struct; typedef data_lift_struct data_lift_t[1]; static inline void data_lift_init(data_lift_t dl, int32_t npol, int32_t *steps, int32_t nsteps){ dl->npol = npol; dl->rr = 1; dl->lstart = 0; dl->nsteps = nsteps; dl->S = 0; int32_t i; dl->steps = (int32_t *)calloc(nsteps, sizeof(int32_t)); for(i = 0; i < nsteps; i++){ dl->steps[i] = steps[i]; } dl->cstep = 0; dl->lend = npol; dl->crt_mult = 0; dl->crt = (mpz_t *)malloc(sizeof(mpz_t) * dl->npol); for(int32_t i = 0; i < dl->npol; i++){ mpz_init(dl->crt[i]); } dl->recon = 0; dl->coef =(int32_t *) calloc(npol, sizeof(int32_t) ); dl->num = malloc(sizeof(mpz_t) * npol); for(i = 0; i < npol; i++){ mpz_init(dl->num[i]); } dl->den = malloc(sizeof(mpz_t) * npol); for(i = 0; i < npol; i++){ mpz_init(dl->den[i]); } mpz_init_set_ui(dl->gden, 1); mpz_init(dl->tmp); dl->start = 0; dl->end = npol; dl->check1 = calloc(npol, sizeof(int)); dl->check2 = calloc(npol, sizeof(int)); } static inline void data_lift_clear(data_lift_t dl){ for(int32_t i = 0; i < dl->npol; i++){ mpz_clear(dl->crt[i]); } free(dl->crt); free(dl->steps); free(dl->coef); for(int32_t i = 0; i < dl->npol; i++){ mpz_clear(dl->num[i]); } free(dl->num); for(int32_t i = 0; i < dl->npol; i++){ mpz_clear(dl->den[i]); } free(dl->den); mpz_clear(dl->gden); mpz_clear(dl->tmp); free(dl->check1); free(dl->check2); } static inline void gb_modpoly_init(gb_modpoly_t modgbs, uint32_t alloc, int32_t *lens, int nv, uint32_t ld, int32_t *lm, int32_t *basis){ modgbs->alloc = alloc; modgbs->nprimes = 0; modgbs->primes = (uint64_t *)calloc(alloc, sizeof(uint64_t)); modgbs->cf_64 = (uint64_t *)calloc(alloc, sizeof(uint64_t)); modgbs->ld = ld; modgbs->nv = nv; modgbs->modpolys = (modpolys_t *)malloc(sizeof(modpolys_t) * ld); modgbs->mb = basis; modgbs->ldm = (int32_t *)calloc(nv*ld, sizeof(int32_t)); for(int32_t i = 0; i < ld; i++){ for(int j = 0; j < nv; j++){ modgbs->ldm[i*nv+j] = lm[i*nv+j]; } } for(uint32_t i = 0; i < ld; i++){ modgbs->modpolys[i]->len = lens[i]; modgbs->modpolys[i]->cf_32 = (uint32_t **)malloc(sizeof(uint32_t *)*lens[i]); modgbs->modpolys[i]->cf_zz = (mpz_t *)malloc(sizeof(mpz_t)*lens[i]); modgbs->modpolys[i]->cf_qq = (mpz_t *)malloc(sizeof(mpz_t)*2*lens[i]); for(uint32_t j = 0; j < lens[i]; j++){ modgbs->modpolys[i]->cf_32[j] = calloc(alloc, sizeof(uint32_t)); mpz_init(modgbs->modpolys[i]->cf_zz[j]); } for(uint32_t j = 0; j < 2 * lens[i]; j++){ mpz_init(modgbs->modpolys[i]->cf_qq[j]); } mpz_init(modgbs->modpolys[i]->lm); mpz_set_ui(modgbs->modpolys[i]->lm, 1); } } static inline void gb_modpoly_realloc(gb_modpoly_t modgbs, uint32_t newalloc, int32_t start){ uint32_t oldalloc = modgbs->alloc; modgbs->alloc += newalloc; uint64_t *newprimes = (uint64_t *)realloc(modgbs->primes, modgbs->alloc * sizeof(uint64_t)); if(newprimes == NULL){ fprintf(stderr, "Problem when reallocating modgbs (primes)\n"); exit(1); } modgbs->primes = newprimes; for(uint32_t i = oldalloc; i < modgbs->alloc; i++){ modgbs->primes[i] = 0; } uint64_t *ncf_64 = (uint64_t *)realloc(modgbs->cf_64, modgbs->alloc * sizeof(uint64_t)); if(ncf_64 == NULL){ fprintf(stderr, "Problem when reallocating modgbs (cfs)\n"); exit(1); } modgbs->cf_64 = ncf_64; for(uint32_t i = oldalloc; i < modgbs->alloc; i++){ modgbs->cf_64[i] = 0; } for(uint32_t i = start; i < modgbs->ld; i++){ for(uint32_t j = 0; j < modgbs->modpolys[i]->len; j++){ uint32_t *newcfs_pol = (uint32_t *)realloc(modgbs->modpolys[i]->cf_32[j], modgbs->alloc * sizeof(uint32_t)); if(newcfs_pol == NULL){ fprintf(stderr, "Problem when reallocating modgbs (cfs_pol)\n"); } modgbs->modpolys[i]->cf_32[j] = newcfs_pol; for(uint32_t k = oldalloc; k < modgbs->alloc; k++){ modgbs->modpolys[i]->cf_32[j][k] = 0; } } } } static inline void display_gbmodpoly_cf_32(FILE *file, gb_modpoly_t modgbs){ fprintf(file, "alloc = %d\n", modgbs->alloc); fprintf(file, "nprimes = %d\n", modgbs->nprimes); fprintf(stderr, "primes = ["); for(uint32_t i = 0; i < modgbs->alloc-1; i++){ fprintf(file, "%lu, ", (unsigned long)modgbs->primes[i]); } fprintf(file, "%lu]\n", (unsigned long)modgbs->primes[modgbs->alloc -1]); fprintf(file, "numpolys = %d\n", modgbs->ld); fprintf(file, "[\n"); for(uint32_t i = 0; i < modgbs->ld; i++){ uint32_t len = modgbs->modpolys[i]->len; fprintf(file, "[%d, ", len); for(uint32_t j = 0; j < len; j++){ fprintf(stderr, "["); for(uint32_t k = 0; k < modgbs->alloc-1; k++){ fprintf(file, "%d, ", modgbs->modpolys[i]->cf_32[j][k]); } if(j < len - 1){ fprintf(file, "%d], ", modgbs->modpolys[i]->cf_32[j][modgbs->alloc-1]); } else{ fprintf(file, "%d]\n", modgbs->modpolys[i]->cf_32[j][modgbs->alloc-1]); } } fprintf(file, "],\n"); } fprintf(file, "]:\n"); } static inline void display_modpoly(FILE *file, gb_modpoly_t modgbs, int32_t pos, data_gens_ff_t *gens){ if(modgbs->modpolys[pos]->len == 0){ display_monomial(file, gens, pos, &modgbs->ldm); return; } if(mpz_cmp_ui(modgbs->modpolys[pos]->lm, 1) != 0){ mpz_out_str(file, 10, modgbs->modpolys[pos]->lm); fprintf(file, "*"); } display_monomial_single(file, gens, pos, &modgbs->ldm); for(int32_t i = modgbs->modpolys[pos]->len-1; i > 0 ; i--){ if((mpz_cmp_ui(modgbs->modpolys[pos]->cf_qq[2*i], 0) != 0 && mpz_cmp_ui(modgbs->modpolys[pos]->cf_qq[2*i], 1) != 0) || mpz_cmp_ui(modgbs->modpolys[pos]->cf_qq[2*i + 1], 1) != 0){ if(mpz_cmp_ui(modgbs->modpolys[pos]->cf_qq[2*i], 0)>0){ fprintf(file, "+"); } mpz_out_str(file, 10, modgbs->modpolys[pos]->cf_qq[2*i]); if(mpz_cmp_ui(modgbs->modpolys[pos]->cf_qq[2*i + 1], 1) != 0){ fprintf(file, "/"); mpz_out_str(file, 10, modgbs->modpolys[pos]->cf_qq[2*i + 1]); } fprintf(file, "*"); } else{ if(mpz_cmp_ui(modgbs->modpolys[pos]->cf_qq[2*i], 0) != 0){ fprintf(file, "+"); } } if(mpz_cmp_ui(modgbs->modpolys[pos]->cf_qq[2*i], 0) != 0){ display_monomial_single(file, gens, i, &modgbs->mb); } fflush(file); } if(mpz_cmp_ui(modgbs->modpolys[pos]->cf_qq[0], 0) > 0){ fprintf(file, "+"); mpz_out_str(file, 10, modgbs->modpolys[pos]->cf_qq[0]); } if(mpz_cmp_ui(modgbs->modpolys[pos]->cf_qq[0], 0) < 0){ mpz_out_str(file, 10, modgbs->modpolys[pos]->cf_qq[0]); } if(mpz_cmp_ui(modgbs->modpolys[pos]->cf_qq[1], 1) != 0){ fprintf(file, "/"); mpz_out_str(file, 10, modgbs->modpolys[pos]->cf_qq[1]); } } static inline void display_gbmodpoly_cf_qq(FILE *file, gb_modpoly_t modgbs, data_gens_ff_t *gens){ int32_t p = modgbs->ld ; if(p==0){ fprintf(file, "[0]:\n"); return; } fprintf(file, "["); for(int i = 0; i < p-1; i++){ display_modpoly(file, modgbs, i, gens); fprintf(file, ", \n"); } display_modpoly(file, modgbs, p-1, gens); fprintf(file, "\n"); fprintf(file, "]:\n"); } static inline void display_lm_gbmodpoly_cf_qq(FILE *file, gb_modpoly_t modgbs, data_gens_ff_t *gens){ int32_t p = modgbs->ld ; if(p==0){ fprintf(file, "[0]:\n"); return; } fprintf(file, "["); for(int i = 0; i < p-1; i++){ if(modgbs->modpolys[i]->len == 0){ display_monomial(file, gens, i, &modgbs->ldm); } else{ display_monomial_single(file, gens, i, &modgbs->ldm); } fprintf(file, ", \n"); } if(modgbs->modpolys[p-1]->len == 0){ display_monomial(file, gens, p-1, &modgbs->ldm); } else{ display_monomial_single(file, gens, p-1, &modgbs->ldm); } fprintf(file, "\n"); fprintf(file, "]:\n"); } static inline void gb_modpoly_clear(gb_modpoly_t modgbs){ free(modgbs->primes); free(modgbs->mb); free(modgbs->ldm); for(uint32_t i = 0; i < modgbs->ld; i++){ for(uint32_t j = 0; j < modgbs->modpolys[i]->len; j++){ free(modgbs->modpolys[i]->cf_32[j]); mpz_clear(modgbs->modpolys[i]->cf_zz[j]); } for(uint32_t j = 0; j < 2 * modgbs->modpolys[i]->len; j++){ mpz_clear(modgbs->modpolys[i]->cf_qq[j]); } mpz_clear(modgbs->modpolys[i]->lm); free(modgbs->modpolys[i]->cf_32); free(modgbs->modpolys[i]->cf_zz); free(modgbs->modpolys[i]->cf_qq); } free(modgbs->modpolys); } static inline int32_t degree(int32_t *mon, int nv){ int32_t deg = 0; for(int i = 0; i < nv; i++){ deg += mon[i]; } return deg; } /* bexp_lm is a list of monomials involving nv variables of increasing degrees return an array of length *nb containing at the i-th position the number of monomials of the i-th degree (hence nb is the number of different degrees). */ static inline int32_t *array_nbdegrees(int32_t *bexp_lm, int len, int nv, int * nb){ *nb = 1; int32_t deg = degree(bexp_lm, nv); for(int32_t i = 1; i < len; i++){ int32_t newdeg = degree(bexp_lm + i * nv, nv); if(deg != newdeg){ (*nb)++; deg = newdeg; } } int32_t *ldeg = calloc(sizeof(int32_t), *nb); deg = degree(bexp_lm, nv); ldeg[0] = 1; int32_t i = 0, j = 1; while(j < len){ int32_t newdeg = degree(bexp_lm + j * nv, nv); if(deg == newdeg){ ldeg[i]++; } else{ i++; ldeg[i] = 1; deg = newdeg; } j++; } return ldeg; } static inline int grevlex_is_less_than(int nv, int32_t* m1, int32_t *m2){ int32_t deg1 = 0, deg2 = 0; for(int i = 0; i < nv; i++){ deg1 += m1[i]; } for(int i = 0; i < nv; i++){ deg2 += m2[i]; } if(deg1 < deg2){ return 1; } if(deg1 > deg2){ return 0; } for(int i = 0; i < nv; i++){ if(m1[i] < m2[i]){ return 0; } } return 1; } static inline int32_t compute_length(int32_t *mon, int nv, int32_t *basis, int dquot){ for(int i = dquot - 1; i >= 0; i--){ if(!grevlex_is_less_than(nv, mon, basis + i * nv)){ return i + 1; } } return 0; } /* * bexp_lm is an array of len monomials with nv variables * basis is an array of dquot monomials with nv variables * (basis of some quotient defined with bexp_lm, all with grevlex order) * basis is sorted increasingly, as for bexp_lm * * returns an array of length len containing the maximum possible lengths * of polynomials with leading terms in bexp_lm (length excluding the * leading term). */ static inline int32_t *array_of_lengths(int32_t *bexp_lm, int len, int32_t *basis, int dquot, int nv){ int32_t *lens = calloc(sizeof(int32_t), len); for(int i = 0; i < len; i++){ lens[i] = compute_length(bexp_lm + (i * nv), nv, basis, dquot); } return lens; } /* returns 0 in case of failure else returns 1 */ static inline int modpgbs_set(gb_modpoly_t modgbs, const bs_t *bs, const ht_t * const ht, const int32_t fc, int32_t *basis, const int dquot, int *mgb, int32_t start, const long elim){ if(modgbs->nprimes >= modgbs->alloc-1){ fprintf(stderr, "Not enough space in modgbs\n"); exit(1); } modgbs->primes[modgbs->nprimes] = fc; len_t i, j, k, idx; len_t len = 0; hm_t *hm = NULL; const len_t nv = ht->nv; const len_t ebl = ht->ebl; const len_t evl = ht->evl; int *evi = (int *)malloc((unsigned long)ht->nv * sizeof(int)); if (ebl == 0) { for (i = 1; i < evl; ++i) { evi[i-1] = i; } } else { for (i = 1; i < ebl; ++i) { evi[i-1] = i; } for (i = ebl+1; i < evl; ++i) { evi[i-2] = i; } } for(i = start; i < modgbs->ld; i++){ idx = bs->lmps[i]; if (bs->hm[idx] == NULL) { fprintf(stderr, " poly is 0\n"); free(evi); exit(1); } else { hm = bs->hm[idx]+OFFSET; len = bs->hm[idx][LENGTH]; } int bc = modgbs->modpolys[i]->len - 1; for (j = 1; j < len; ++j) { uint32_t c = bs->cf_32[bs->hm[idx][COEFFS]][j]; for (k = 0; k < nv; ++k) { mgb[k] = ht->ev[hm[j]][evi[k]]; } while(!is_equal_exponent_elim(mgb, basis + (bc * (nv - elim)), nv, elim)){ bc--; } modgbs->modpolys[i]->cf_32[bc][modgbs->nprimes] = c; bc--; } } modgbs->nprimes++; free(evi); return 1; } static inline int32_t maxbitsize_gens(data_gens_ff_t *gens, len_t ngens){ if(gens->field_char != 0){ return -1; } const int32_t *lens = gens->lens; mpz_t **cfs = gens->mpz_cfs; int32_t off = 0; int32_t mbs = 0; for(int32_t i = 0; i < ngens; i++){ for(int32_t j = off; j < off + lens[i]; ++j){ mbs = MAX(mbs, mpz_sizeinbase(*(cfs[2*j]), 2) + mpz_sizeinbase(*(cfs[2*j+1]), 2)); } off += lens[i]; } return mbs; } static inline int32_t compute_num_gb(int32_t *bexp_lm, int32_t len, int nv, int nev){ if(nev){ for(int32_t i = 0; i < len; i++){ for(int32_t j = 0; j < nev; j++){ if(bexp_lm[i*nv+j]){ return i; } } } return len; } return len; } static int32_t * gb_modular_trace_learning(gb_modpoly_t modgbs, int32_t *mgb, int32_t *num_gb, int32_t **leadmons, trace_t *trace, ht_t *tht, bs_t *bs_qq, ht_t *gbht, md_t *st, const int32_t fc, int info_level, int print_gb, int truncate_lifting, int *dim, long *dquot_ori, int32_t start, data_gens_ff_t *gens, int32_t maxbitsize, files_gb *files, int *success) { double ca0, rt; ca0 = realtime(); bs_t *bs = NULL; /* if(gens->field_char){ */ int32_t err = 0; st->f4_qq_round = 1; bs = core_gba(bs_qq, st, &err, fc); if (err) { printf("Problem with F4, stopped computation.\n"); exit(1); } rt = realtime()-ca0; const ht_t *bht = bs->ht; if(info_level > 1){ fprintf(stderr, "Learning phase %.2f Gops/sec\n", (st->trace_nr_add+st->trace_nr_mult)/1000.0/1000.0/rt); } if(info_level > 2){ fprintf(stderr, "------------------------------------------\n"); fprintf(stderr, "#ADDITIONS %13lu\n", (unsigned long)st->trace_nr_add * 1000); fprintf(stderr, "#MULTIPLICATIONS %13lu\n", (unsigned long)st->trace_nr_mult * 1000); fprintf(stderr, "#REDUCTIONS %13lu\n", (unsigned long)st->trace_nr_red); fprintf(stderr, "------------------------------------------\n"); } /* Leading monomials from Grobner basis */ int32_t *bexp_lm = get_lm_from_bs(bs, bht); leadmons[0] = bexp_lm; int32_t len = bs->lml; num_gb[0] = compute_num_gb(bexp_lm, len, bht->nv, st->nev); int32_t *bexp_lm2 = NULL; if(st->nev){ bexp_lm2 = calloc(num_gb[0]*(bht->nv - st->nev), sizeof(int32_t)); for(int32_t i = 0; i < num_gb[0]; i++){ for(int j = 0; j < bht->nv - st->nev; j++){ bexp_lm2[i*(bht->nv - st->nev) + j] = bexp_lm[i*bht->nv + st->nev + j]; } } leadmons[0] = bexp_lm2; } /************************************************/ /************************************************/ long dquot = 0; int32_t *lmb; if(st->nev){ lmb = monomial_basis_enlarged(num_gb[0], bht->nv - st->nev, bexp_lm2, &dquot); } else{ lmb = monomial_basis_enlarged(num_gb[0], bht->nv, bexp_lm, &dquot); } /************************************************/ /************************************************/ /* int32_t *lens = array_of_lengths(bexp_lm, num_gb[0], lmb, dquot, bht->nv); */ int32_t *lens = array_of_lengths(leadmons[0], num_gb[0], lmb, dquot, bht->nv - st->nev); if(truncate_lifting != 0 && truncate_lifting < num_gb[0]){ gb_modpoly_init(modgbs, 2, lens, bht->nv - st->nev, truncate_lifting, leadmons[0], lmb); } else{ gb_modpoly_init(modgbs, 2, lens, bht->nv - st->nev, num_gb[0], leadmons[0], lmb); } modpgbs_set(modgbs, bs, bht, fc, lmb, dquot, mgb, start, st->nev); if(bs->lml == 1){ if(info_level){ fprintf(stderr, "Grobner basis has a single element\n"); } int is_empty = 1; for(int i = 0; i < bht->nv; i++){ if(bexp_lm[i]!=0){ is_empty = 0; } } if(is_empty){ *dquot_ori = 0; *dim = 0; /* if(info_level){ */ /* fprintf(stderr, "No solution\n"); */ /* } */ /* print_ff_basis_data( */ /* files->out_file, "a", bs, bht, st, gens, print_gb); */ free_basis_without_hash_table(&(bs)); return NULL; } } /**************************************************/ free_basis_without_hash_table(&(bs)); return lmb; } static void gb_modular_trace_application(gb_modpoly_t modgbs, int32_t *mgb, int32_t *num_gb, int32_t **leadmons_ori, int32_t **leadmons_current, trace_t **btrace, ht_t **btht, bs_t *bs_qq, ht_t **gbht, md_t *st, const int32_t fc, int info_level, bs_t **obs, int32_t *lmb_ori, int32_t dquot_ori, primes_t *lp, int32_t start, data_gens_ff_t *gens, double *stf4, int *bad_primes){ double rt = realtime(); st->info_level = 0; st->f4_qq_round = 2; /* tracing phase */ /* F4 and FGLM are run using a single thread */ /* st->nthrds is reset to its original value afterwards */ /*at the moment multi-threading is not supprted here*/ memset(bad_primes, 0, (unsigned long)st->nprimes * sizeof(int)); bs_t *bs = NULL; int32_t error = 0; bs = core_gba(bs_qq, st, &error, lp->p[0]); *stf4 = realtime()-rt; /* if(st->laopt > 40){ bs = modular_f4(bs_qq, bht[0], st, lp->p[0]); } else{ bs = gba_trace_application_phase(btrace[0], btht[0], bs_qq, bht[0], st, lp->p[0]); } */ ht_t **bht = &(bs->ht); if (bs == NULL) { bad_primes[0] = 1; return; } int32_t lml = bs->lml; if (st->nev > 0) { int32_t j = 0; for (len_t i = 0; i < bs->lml; ++i) { if ((*bht)->ev[bs->hm[bs->lmps[i]][OFFSET]][0] == 0) { bs->lm[j] = bs->lm[i]; bs->lmps[j] = bs->lmps[i]; ++j; } } lml = j; } if (lml != num_gb[0]) { if (bs != NULL) { free_basis_and_only_local_hash_table_data(&bs); } return; } if(st->nev){ get_lm_from_bs_trace_elim(bs, bht[0], leadmons_current[0], num_gb[0]); } else{ get_lm_from_bs_trace(bs, bht[0], leadmons_current[0]); } if(!equal_staircase(leadmons_current[0], leadmons_ori[0], num_gb[0], num_gb[0], bht[0]->nv - st->nev)){ bad_primes[0] = 1; } if(!bad_primes[0] && bs != NULL){ /* copy of data for multi-mod computation */ modpgbs_set(modgbs, bs, bht[0], lp->p[0], lmb_ori, dquot_ori, mgb, start, st->nev); } if (bs != NULL) { free_basis_and_only_local_hash_table_data(&bs); } } static inline void choose_coef_to_lift(gb_modpoly_t modgbs, data_lift_t dlift){ uint32_t ld = modgbs->ld; for(int32_t i = 0; i < ld; i++){ uint32_t d = 0; uint32_t len = modgbs->modpolys[i]->len; while(d < len - 1){ if(modgbs->modpolys[i]->cf_32[d][0]){ dlift->coef[i] = d; break; } else{ d++; } } } } /* Incremental CRT (called once FLINT multi_CRT has been called) */ /* mod is the current modulus */ static inline void incremental_dlift_crt(gb_modpoly_t modgbs, data_lift_t dlift, int32_t *coef, mpz_t *mod_p, mpz_t *prod_p, int thrds){ /* all primes are assumed to be good primes */ mpz_mul_ui(prod_p[0], mod_p[0], modgbs->primes[modgbs->nprimes - 1 ]); for(int32_t k = dlift->lstart; k <= dlift->lend; k++){ uint32_t c = modgbs->modpolys[k]->cf_32[coef[k]][modgbs->nprimes - 1 ]; mpz_CRT_ui(dlift->crt[k], dlift->crt[k], mod_p[0], c, modgbs->primes[modgbs->nprimes - 1 ], prod_p[0], dlift->tmp, 1); } mpz_set(mod_p[0], prod_p[0]); } /* Incremental CRT on the whole array of witness coefficients */ /* mod is the current modulus */ static inline void incremental_dlift_crt_full(gb_modpoly_t modgbs, data_lift_t dl, int32_t *coef, mpz_t mod_p, mpz_t prod_p, int thrds){ uint64_t newprime = modgbs->primes[modgbs->nprimes - 1 ]; /* all primes are assumed to be good primes */ mpz_mul_ui(prod_p, mod_p, (uint32_t)newprime); for(int32_t k = 0; k < dl->end; k++){ uint64_t c = modgbs->modpolys[k]->cf_32[coef[k]][modgbs->nprimes - 1 ]; mpz_CRT_ui(dl->crt[k], dl->crt[k], mod_p, c, newprime, prod_p, dl->tmp, 1); } mpz_set(mod_p, prod_p); } static inline void crt_lift_modgbs(gb_modpoly_t modgbs, data_lift_t dlift, int32_t start, int32_t end){ /* Data needed by multi CRT functions */ fmpz_comb_t comb; fmpz_comb_temp_t comb_temp; fmpz_comb_init(comb, modgbs->primes, modgbs->nprimes); fmpz_comb_temp_init(comb_temp, comb); fmpz_t y; fmpz_init(y); modpolys_t *polys = modgbs->modpolys; for(int32_t k = start; k < end; k++){ if(dlift->check1[k] >= 1){ for(int32_t l = 0; l < polys[k]->len; l++){ for(uint32_t i = 0; i < modgbs->nprimes-1; i++){ modgbs->cf_64[i] = polys[k]->cf_32[l][i]; } fmpz_multi_CRT_ui(y, modgbs->cf_64, comb, comb_temp, 1); fmpz_get_mpz(polys[k]->cf_zz[l], y); } } } fmpz_clear(y); fmpz_comb_temp_clear(comb_temp); fmpz_comb_clear(comb); } static inline void set_recdata(data_lift_t dl, rrec_data_t rd1, rrec_data_t rd2, mpz_t mod_p){ mpz_fdiv_q_2exp(rd1->N, mod_p, 1); if(dl->lstart){ mpz_set(rd2->N, rd1->N); mpz_sqrt(rd2->N, rd2->N); mpz_set(rd2->D, rd2->N); mpz_root(rd1->D, rd1->N, 3); mpz_fdiv_q(rd1->N, rd1->N, rd1->D); } else{ mpz_sqrt(rd1->N, rd1->N); mpz_set(rd1->D, rd1->N); mpz_set(rd2->N, rd1->N); mpz_set(rd2->D, rd1->D); } } /* returns the index of the poly if some of its coeff could not be lifted else returns -1 */ static inline int ratrecon_lift_modgbs(gb_modpoly_t modgbs, data_lift_t dl, int32_t start, int32_t end, mpz_t mod_p, rrec_data_t rd1, rrec_data_t rd2){ mpz_t rnum, rden; mpz_init(rnum); mpz_init(rden); modpolys_t *polys = modgbs->modpolys; set_recdata(dl, rd1, rd2, mod_p); for(int32_t k = start; k < end; k++){ if(dl->check1[k] >= 1){ mpz_set_ui(dl->tmp, 1); for(int32_t l = 0; l < polys[k]->len; l++){ if(ratreconwden(rnum, rden, polys[k]->cf_zz[l], mod_p, dl->den[k], rd1)){ mpz_set(polys[k]->cf_qq[2*l], rnum); mpz_set(polys[k]->cf_qq[2*l + 1], rden); mpz_lcm(dl->tmp, dl->tmp, rden); } else{ mpz_set_ui(dl->gden, 1); dl->check2[k] = 0; mpz_clear(rnum); mpz_clear(rden); return k; } } mpz_set(polys[k]->lm, dl->den[k]); for(int32_t l = 0; l < polys[k]->len; l++){ mpz_mul(polys[k]->cf_qq[2*l], polys[k]->cf_qq[2*l], dl->tmp); mpz_divexact(polys[k]->cf_qq[2*l], polys[k]->cf_qq[2*l], polys[k]->cf_qq[2*l+1]); mpz_set_ui(polys[k]->cf_qq[2*l+1], 1); } mpz_mul(polys[k]->lm, polys[k]->lm, dl->tmp); dl->check2[k] = 1; } else{ mpz_clear(rnum); mpz_clear(rden); return k; } } mpz_clear(rnum); mpz_clear(rden); return end; } /* returns (coef == num / den mod prime) */ static inline int verif_coef(mpz_t num, mpz_t den, uint32_t prime, uint32_t coef){ uint32_t lc = mpz_fdiv_ui(den, prime); lc = mod_p_inverse_32(lc, prime); uint64_t c = mpz_fdiv_ui(num, prime); c *= lc; c = c % prime; return (c==coef); } static inline int verif_lifted_basis(gb_modpoly_t modgbs, data_lift_t dl, int thrds){ /* verification of the basis is performed at the very end of the computation */ if(dl->check1[dl->end-1] == 0){ return 1; } int b = 1; mpz_t den; mpz_init(den); for(int32_t k = 0; k < modgbs->ld; k++){ if(dl->check1[k]>=1 && dl->check2[k] > 0 && dl->check2[k] < NBCHECK){ for(int i = 0; i < thrds; i++){ uint32_t prime = modgbs->primes[modgbs->nprimes - (thrds - i) ]; for(int32_t c = 0; c < modgbs->modpolys[k]->len; c++){ mpz_mul(den, modgbs->modpolys[k]->lm, modgbs->modpolys[k]->cf_qq[2*c+1]); uint32_t coef = modgbs->modpolys[k]->cf_32[c][modgbs->nprimes - (thrds - i) ]; int b = verif_coef(modgbs->modpolys[k]->cf_qq[2*c], den, prime, coef); if(!b){ dl->check2[k] = 0; mpz_set_ui(dl->gden, 1); b = 0; mpz_clear(den); return b; } } dl->check2[k]++; } } } mpz_clear(den); return b; } static inline int verif_lifted_rational_wcoef(gb_modpoly_t modgbs, data_lift_t dl, int thrds){ for(int32_t k = dl->lstart; k < dl->lend; k++){ if(dl->check1[k]==0){ /* too early to perform the verification */ return k; } for(int i = 0; i < thrds; i++){ uint32_t prime = modgbs->primes[modgbs->nprimes - (thrds - i) ]; uint32_t coef = modgbs->modpolys[k]->cf_32[dl->coef[k]][modgbs->nprimes - (thrds - i) ]; int boo = verif_coef(dl->num[k], dl->den[k], prime, coef); if(!boo){ for(int32_t kk = k; kk < dl->end; kk++){ dl->check1[kk] = 0; } dl->start = k; return k; } dl->start = MIN(dl->start + 1, dl->lend); dl->check1[k]++; } } return -1; } /* returns 0 iff rational number could not be lifted */ static inline int reconstructcoeff(data_lift_t dl, int32_t i, mpz_t mod_p, rrec_data_t recdata1, rrec_data_t recdata2){ int b = ratreconwden(dl->num[i], dl->den[i], dl->crt[i], mod_p, dl->gden, recdata1); if(b){ mpz_mul(dl->den[i], dl->den[i], dl->gden); mpz_gcd(dl->tmp, dl->den[i], dl->num[i]); mpz_divexact(dl->num[i], dl->num[i], dl->tmp); mpz_divexact(dl->den[i], dl->den[i], dl->tmp); mpz_set(dl->gden, dl->den[i]); } else{ b = ratrecon(dl->num[i], dl->den[i], dl->crt[i], mod_p, recdata2); if(b){ mpz_set(dl->gden, dl->den[i]); } } return b; } static void ratrecon_gb(gb_modpoly_t modgbs, data_lift_t dl, mpz_t mod_p, mpz_t prod_p, rrec_data_t recdata1, rrec_data_t recdata2, int thrds, double *st_crt, double *st_rrec){ double st = realtime(); verif_lifted_rational_wcoef(modgbs, dl, thrds); int b = verif_lifted_basis(modgbs, dl, thrds); if(b == 0){ for(int32_t i = 0; i < modgbs->ld; i++){ if(dl->check2[i] == 0){ dl->lstart = i; break; } } } *st_rrec += realtime()-st; if(dl->lstart != dl->start){ crt_lift_modgbs(modgbs, dl, dl->lstart, dl->start); *st_crt += realtime() - st; st = realtime(); dl->start = ratrecon_lift_modgbs(modgbs, dl, dl->lstart, dl->start, mod_p, recdata1, recdata2); *st_rrec += realtime()-st; } dl->lstart = dl->start; st = realtime(); incremental_dlift_crt_full(modgbs, dl, dl->coef, mod_p, prod_p, thrds); *st_crt += realtime() - st; /********************************************************/ /* RATRECON WITNESS COEFFS */ /********************************************************/ if(dl->lstart == 0){ mpz_set_ui(dl->gden, 1); } set_recdata(dl, recdata1, recdata2, mod_p); st = realtime(); if(modgbs->nprimes % dl->rr == 0){ for(int32_t i = dl->lstart; i < dl->lend; i++){ int b = reconstructcoeff(dl, i, mod_p, recdata1, recdata2); if(!b){ dl->check1[i] = 0; break; } else{ dl->check1[i]++; } } } *st_rrec += realtime()-st; } long max_bit_size_gb(gb_modpoly_t modgbs){ long nb = 0; for(uint32_t i = 0; i < modgbs->ld; i++){ for(uint32_t j = 0; j < modgbs->modpolys[i]->len; j++){ nb = MAX(nb, mpz_sizeinbase(modgbs->modpolys[i]->cf_qq[2*j], 2)); nb = MAX(nb, mpz_sizeinbase(modgbs->modpolys[i]->cf_qq[2*j + 1], 2)); } nb = MAX(nb, mpz_sizeinbase(modgbs->modpolys[i]->lm, 2)); } return nb; } /* - returns 0 if the computation went ok - returns 1 in case of failure - returns -3 if meta data were not ok - returns -4 if there are too many bad primes */ int msolve_gbtrace_qq( gb_modpoly_t modgbs, data_gens_ff_t *gens, msflags_t flags){ double st0 = realtime(); int *dim_ptr = &flags->dim; long *dquot_ptr = &flags->dquot; int32_t ht_size = flags->ht_size; int32_t nr_threads = flags->nr_threads; int32_t max_nr_pairs = flags->max_nr_pairs; int32_t elim_block_len = flags->elim_block_len; int32_t reset_ht = flags->reset_ht; int32_t la_option = flags->la_option; int32_t use_signatures = flags->use_signatures; int32_t info_level = flags->info_level; int32_t pbm_file = flags->pbm_file; int32_t print_gb = flags->print_gb; int32_t truncate_lifting = flags->truncate_lifting; files_gb *files = flags->files; uint32_t field_char = gens->field_char; const void *cfs = gens->mpz_cfs; if(gens->field_char){ cfs = gens->cfs; } else{ cfs = gens->mpz_cfs; } int mon_order = 0; int32_t nr_vars = gens->nvars; int32_t nr_gens = gens->ngens; int reduce_gb = 1; int32_t nr_nf = 0; const uint32_t prime_start = pow(2, 30); /* initialize stuff */ md_t *st = allocate_meta_data(); int *invalid_gens = NULL; int res = validate_input_data(&invalid_gens, cfs, gens->lens, &field_char, &mon_order, &elim_block_len, &nr_vars, &nr_gens, &nr_nf, &ht_size, &nr_threads, &max_nr_pairs, &reset_ht, &la_option, &use_signatures, &reduce_gb, &info_level); /* all data is corrupt */ if (res == -1) { fprintf(stderr, "Invalid input generators, msolve now terminates.\n"); free(invalid_gens); return -3; } /* checks and set all meta data. if a nonzero value is returned then * some of the input data is corrupted. */ if (check_and_set_meta_data_trace(st, gens->lens, gens->exps, cfs, invalid_gens, field_char, mon_order, elim_block_len, nr_vars, nr_gens, nr_nf, ht_size, nr_threads, max_nr_pairs, reset_ht, la_option, use_signatures, reduce_gb, prime_start, nr_threads /* nr_primes */, pbm_file, info_level)) { fprintf(stderr, "Something went wrong when checking and setting meta data, msolve now terminates.\n"); free(st); return -3; } mstrace_t msd; initialize_mstrace(msd, st); /* read in ideal, move coefficients to integers */ import_input_data(msd->bs_qq, st, 0, st->ngens_input, gens->lens, gens->exps, cfs, invalid_gens); free(invalid_gens); invalid_gens = NULL; print_initial_statistics(stderr, st); /* for faster divisibility checks, needs to be done after we have * read some input data for applying heuristics */ calculate_divmask(msd->bht); /* sort initial elements, smallest lead term first */ sort_r(msd->bs_qq->hm, (unsigned long)msd->bs_qq->ld, sizeof(hm_t *), initial_input_cmp, msd->bht); if(gens->field_char == 0){ remove_content_of_initial_basis(msd->bs_qq); /* generate lucky prime numbers */ generate_lucky_primes(msd->lp, msd->bs_qq, st->prime_start, st->nthrds); } else{ msd->lp->old = 0; msd->lp->ld = 1; msd->lp->p = calloc(1, sizeof(uint32_t)); normalize_initial_basis(msd->bs_qq, st->gfc); } uint32_t prime = 0; uint32_t primeinit = 0; uint32_t lprime = 1303905299; srand(time(0)); prime = next_prime(rand() % (1303905301 - (1<<30) + 1) + (1<<30)); while(gens->field_char==0 && is_lucky_prime_ui(prime, msd->bs_qq)){ prime = next_prime(rand() % (1303905301 - (1<<30) + 1) + (1<<30)); } primeinit = prime; msd->lp->p[0] = primeinit; if(gens->field_char){ msd->lp->p[0] = gens->field_char; primeinit = gens->field_char; } int success = 1; int32_t maxbitsize = maxbitsize_gens(gens, st->ngens); int learn = 1, apply = 1, nprimes = 0; double stf4 = 0; rrec_data_t recdata1, recdata2; initialize_rrec_data(recdata1); initialize_rrec_data(recdata2); data_lift_t dlift; /* indicates that dlift has been already initialized */ int dlinit = 0; double st_crt = 0; double st_rrec = 0; uint32_t nbadprimes = 0; while(learn){ int32_t *lmb_ori = gb_modular_trace_learning(modgbs, msd->mgb, msd->num_gb, msd->leadmons_ori, msd->btrace[0], msd->tht, msd->bs_qq, msd->bht, st, msd->lp->p[0], info_level, print_gb, truncate_lifting, dim_ptr, dquot_ptr, 0, gens, maxbitsize, files, &success); /*lmb_ori can be NULL when gb = [1]*/ if(lmb_ori == NULL || print_gb == 1){ if(dlinit){ data_lift_clear(dlift); } free_mstrace(msd, st); free_rrec_data(recdata1); free_rrec_data(recdata2); free(st); return 0; } apply = 1; gb_modpoly_realloc(modgbs, 1, dlift->S); #ifdef DEBUGGBLIFT display_gbmodpoly_cf_32(stderr, modgbs); #endif if(!dlinit){ int nb = 0; int32_t *ldeg = array_nbdegrees((*msd->leadmons_ori), msd->num_gb[0], msd->bht->nv - st->nev, &nb); data_lift_init(dlift, modgbs->ld, ldeg, nb); choose_coef_to_lift(modgbs, dlift); free(ldeg); dlinit = 1; } if(info_level){ int s= 0; for(int i = 0; i < dlift->nsteps; i++){ fprintf(stderr, "[%d]", dlift->steps[i]); s+=dlift->steps[i]; } fprintf(stderr, "\n"); if(s > 1){ fprintf(stderr, "%d polynomials to lift\n", s); } } if(lmb_ori == NULL || success == 0 || gens->field_char) { apply = 0; if(dlinit){ data_lift_clear(dlift); } gb_modpoly_clear(modgbs); free_mstrace(msd, st); free_rrec_data(recdata1); free_rrec_data(recdata2); free(st); fprintf(stderr, "Something went wrong in the learning phase, msolve restarts."); return msolve_gbtrace_qq(modgbs, gens, flags); } /* duplicate data for multi-threaded multi-mod computation */ duplicate_data_mthread_gbtrace(st->nthrds, msd->bs_qq, st, msd->num_gb, msd->leadmons_ori, msd->leadmons_current, msd->btrace); /* copy of hash tables for tracer application */ msd->blht[0] = msd->bht; for(int i = 1; i < st->nthrds; i++){ ht_t *lht = copy_hash_table(msd->bht); msd->blht[i] = lht; } if(info_level){ fprintf(stderr, "\nStarts multi-modular computations\n"); } learn = 0; while(apply){ prime = next_prime(prime); if(prime >= lprime){ prime = next_prime(1<<30); } /* generate lucky prime numbers */ msd->lp->p[0] = prime; while(is_lucky_prime_ui(prime, msd->bs_qq) || prime==primeinit){ prime = next_prime(prime); if(prime >= lprime){ prime = next_prime(1<<30); } msd->lp->p[0] = prime; } int nthrds = 1; /* mono-threaded mult-mid comp */ for(len_t i = 1; i < nthrds/* st->nthrds */; i++){ prime = next_prime(prime); if(prime >= lprime){ prime = next_prime(1<<30); } msd->lp->p[i] = prime; while(is_lucky_prime_ui(prime, msd->bs_qq) || prime==primeinit){ prime = next_prime(prime); if(prime >= lprime){ prime = next_prime(1<<30); } msd->lp->p[i] = prime; } } prime = msd->lp->p[nthrds /* st->nthrds */ - 1]; if(modgbs->alloc <= nprimes + 2){ gb_modpoly_realloc(modgbs, 16*st->nthrds, dlift->S); } gb_modular_trace_application(modgbs, msd->mgb, msd->num_gb, msd->leadmons_ori, msd->leadmons_current, msd->btrace, msd->btht, msd->bs_qq, msd->blht, st, field_char, 0, /* info_level, */ msd->bs, lmb_ori, *dquot_ptr, msd->lp, dlift->S, gens, &stf4, msd->bad_primes); /* nprimes += st->nthrds; */ nprimes += 1; /* at the moment, multi-mod comp is mono-threaded */ if(nprimes == 1){ if(info_level>2){ fprintf(stderr, "------------------------------------------\n"); fprintf(stderr, "#ADDITIONS %13lu\n", (unsigned long)st->application_nr_add * 1000); fprintf(stderr, "#MULTIPLICATIONS %13lu\n", (unsigned long)st->application_nr_mult * 1000); fprintf(stderr, "#REDUCTIONS %13lu\n", (unsigned long)st->application_nr_red); fprintf(stderr, "------------------------------------------\n"); } if(info_level>1){ fprintf(stderr, "Application phase %.2f Gops/sec\n", (st->application_nr_add+st->application_nr_mult)/1000.0/1000.0/(stf4)); fprintf(stderr, "Elapsed time: %.2f\n", stf4); } } int bad = 0; for(int i = 0; i < nthrds/* st->nthrds */; i++){ if(msd->bad_primes[i] == 1){ bad = 1; nbadprimes++; } } if(nbadprimes == nprimes){ fprintf(stderr, "Too many bad primes, computation will restart\n"); free_mstrace(msd, st); if(dlinit){ data_lift_clear(dlift); } free_rrec_data(recdata1); free_rrec_data(recdata2); free(st); return msolve_gbtrace_qq(modgbs, gens, flags); } int lstart = dlift->lstart; double ost_rrec = st_rrec; double ost_crt = st_crt; if(!bad){ ratrecon_gb(modgbs, dlift, msd->mod_p, msd->prod_p, recdata1, recdata2, nthrds/* st->nthrds */, &st_crt, &st_rrec); } if((st_crt -ost_crt) + (st_rrec - ost_rrec) > dlift->rr * stf4){ dlift->rr = 2*dlift->rr; if(info_level){ fprintf(stderr, "(->%d)", dlift->rr); } } if(info_level){ if(!(nprimes & (nprimes - 1))){ fprintf(stderr, "{%d}", nprimes); } } apply = 0; for(len_t i = 0; i < modgbs->ld; i++){ if(dlift->check2[i] < NBCHECK){ apply = 1; break; } } if(dlift->lstart != lstart){ if(info_level){ fprintf(stderr, "<%.2f%%>", 100* (float)MIN((dlift->lstart + 1), modgbs->ld)/modgbs->ld); } lstart = dlift->lstart; } /* this is where learn could be reset to 1 */ /* but then duplicated datas and others should be free-ed */ } } if(info_level){ fprintf(stderr, "\nCRT time = %.2f, Rational reconstruction time = %.2f\n", st_crt, st_rrec); } if(info_level){ long nbits = max_bit_size_gb(modgbs); fprintf(stderr, "Maximum bit size of the coefficients: %ld\n", nbits); fprintf(stderr, "%d primes used. \nElapsed time: %.2f\n", nprimes, realtime()-st0); } free_mstrace(msd, st); if(dlinit){ data_lift_clear(dlift); } free_rrec_data(recdata1); free_rrec_data(recdata2); free(st); return 0; } /* Function which is called by core_msolve */ void print_msolve_gbtrace_qq(data_gens_ff_t *gens, msflags_t flags){ gb_modpoly_t modgbs; msolve_gbtrace_qq(modgbs, gens, flags); FILE *ofile; if (flags->files->out_file != NULL) { ofile = fopen(flags->files->out_file, "w+"); } else { ofile = stdout; } if (flags->print_gb == 1) { fprintf(ofile, "#Leading ideal data\n"); } else { if (flags->print_gb > 1) { if(flags->truncate_lifting>0){ fprintf(ofile, "#Truncated reduced Groebner basis data\n"); } else{ fprintf(ofile, "#Reduced Groebner basis data\n"); } } } fprintf(ofile, "#---\n"); fprintf(ofile, "#field characteristic: 0\n"); fprintf(ofile, "#variable order: "); for (int i = gens->elim; i < gens->nvars-1; ++i) { fprintf(ofile, "%s, ", gens->vnames[i]); } fprintf(ofile, "%s\n", gens->vnames[gens->nvars-1]); fprintf(ofile, "#monomial order: graded reverse lexicographical\n"); if (modgbs->ld == 1) { fprintf(ofile, "#length of basis: 1 element\n"); } else { fprintf(ofile, "#length of basis: %u elements sorted by increasing leading monomials\n", modgbs->ld); } fprintf(ofile, "#---\n"); if (flags->files->out_file != NULL) { fclose(ofile); } if(flags->print_gb > 1){ if(flags->files->out_file != NULL){ FILE *ofile = fopen(flags->files->out_file, "a+"); display_gbmodpoly_cf_qq(ofile, modgbs, gens); fclose(ofile); } else{ display_gbmodpoly_cf_qq(stdout, modgbs, gens); } } if(flags->print_gb == 1){ if(flags->files->out_file != NULL){ FILE *ofile = fopen(flags->files->out_file, "a+"); display_lm_gbmodpoly_cf_qq(ofile, modgbs, gens); fclose(ofile); } else{ display_lm_gbmodpoly_cf_qq(stdout, modgbs, gens); } } gb_modpoly_clear(modgbs); } msolve-0.6.5/src/msolve/lifting.c000066400000000000000000000247571456710632100167470ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ /* Initialization of sparse fglm matrix for crt */ static inline void crt_mpz_matfglm_initset(crt_mpz_matfglm_t crt_mat, sp_matfglm_t *mod_mat){ crt_mat->ncols = mod_mat->ncols; crt_mat->nrows = mod_mat->nrows; crt_mat->dense_mat = calloc(crt_mat->ncols*crt_mat->nrows, sizeof(mpz_t)); uint64_t sz = crt_mat->nrows * crt_mat->ncols; for(uint64_t i = 0; i < sz; i++){ mpz_init_set_ui(crt_mat->dense_mat[i], mod_mat->dense_mat[i]); } long diff = crt_mat->ncols - crt_mat->nrows; crt_mat->triv_idx = calloc(diff, sizeof(uint32_t)); crt_mat->triv_pos = calloc(diff, sizeof(uint32_t)); crt_mat->dense_idx = calloc(crt_mat->nrows, sizeof(uint32_t)); crt_mat->dst = calloc(crt_mat->nrows, sizeof(uint32_t)); for(long i = 0; i < diff; i++){ crt_mat->triv_idx[i]= mod_mat->triv_idx[i]; crt_mat->triv_pos[i]= mod_mat->triv_pos[i]; } for(long i = 0; i < crt_mat->nrows; i++){ crt_mat->dense_idx[i] = mod_mat->dense_idx[i]; crt_mat->dst[i] = mod_mat->dst[i]; } } /* Initialization of sparse mpz fglm matrix */ static inline void mpz_matfglm_initset(mpz_matfglm_t mpz_mat, sp_matfglm_t *mod_mat){ mpz_mat->ncols = mod_mat->ncols; mpz_mat->nrows = mod_mat->nrows; mpz_mat->dense_mat = calloc(mpz_mat->ncols*mpz_mat->nrows, sizeof(mpz_t)); uint64_t sz = mpz_mat->nrows * mpz_mat->ncols; for(uint64_t i = 0; i < sz; i++){ mpz_init_set_ui(mpz_mat->dense_mat[i], 0); } mpz_mat->denoms = calloc(mpz_mat->nrows, sizeof(mpz_t)); for(uint64_t i = 0; i < mpz_mat->nrows; i++){ mpz_init_set_ui(mpz_mat->denoms[i], 1); } long diff = mpz_mat->ncols - mpz_mat->nrows; mpz_mat->triv_idx = calloc(diff, sizeof(uint32_t)); mpz_mat->triv_pos = calloc(diff, sizeof(uint32_t)); mpz_mat->dense_idx = calloc(mpz_mat->nrows, sizeof(uint32_t)); mpz_mat->dst = calloc(mpz_mat->nrows, sizeof(uint32_t)); for(long i = 0; i < diff; i++){ mpz_mat->triv_idx[i]= mod_mat->triv_idx[i]; mpz_mat->triv_pos[i]= mod_mat->triv_pos[i]; } for(long i = 0; i < mpz_mat->nrows; i++){ mpz_mat->dense_idx[i] = mod_mat->dense_idx[i]; mpz_mat->dst[i] = mod_mat->dst[i]; } } /* Initialization of sparse fglm matrix for rational reconstruction */ static inline void mpq_matfglm_initset(mpq_matfglm_t mpq_mat, sp_matfglm_t *mod_mat){ mpq_mat->ncols = mod_mat->ncols; mpq_mat->nrows = mod_mat->nrows; mpq_mat->dense_mat = calloc(2*mpq_mat->ncols*mpq_mat->nrows, sizeof(mpz_t)); uint64_t nc = 2*mpq_mat->ncols; for(uint32_t i = 0; i < mpq_mat->nrows; i++){ uint64_t c = 2*i*mpq_mat->ncols; for(uint32_t j = 0; j < nc; j++){ mpz_init_set_ui(mpq_mat->dense_mat[c+j], 0); j++; mpz_init_set_ui(mpq_mat->dense_mat[c+j], 1); } } long diff = mpq_mat->ncols - mpq_mat->nrows; mpq_mat->triv_idx = calloc(diff, sizeof(uint32_t)); mpq_mat->triv_pos = calloc(diff, sizeof(uint32_t)); mpq_mat->dense_idx = calloc(mpq_mat->nrows, sizeof(uint32_t)); mpq_mat->dst = calloc(mpq_mat->nrows, sizeof(uint32_t)); for(long i = 0; i < diff; i++){ mpq_mat->triv_idx[i]= mod_mat->triv_idx[i]; mpq_mat->triv_pos[i]= mod_mat->triv_pos[i]; } for(long i = 0; i < mpq_mat->nrows; i++){ mpq_mat->dense_idx[i] = mod_mat->dense_idx[i]; mpq_mat->dst[i] = mod_mat->dst[i]; } } static inline void trace_det_initset(trace_det_fglm_mat_t trace_det, uint32_t trace_mod, uint32_t det_mod, uint32_t tridx, uint32_t detidx){ mpz_init_set_ui(trace_det->trace_crt, trace_mod); mpz_init_set_ui(trace_det->det_crt, det_mod); mpz_init_set_ui(trace_det->trace_num, 0); mpz_init_set_ui(trace_det->trace_den, 1); mpz_init_set_ui(trace_det->det_num, 0); mpz_init_set_ui(trace_det->det_den, 1); mpz_init(trace_det->tmp); trace_det->check_trace = 0; trace_det->check_det = 0; trace_det->done_trace = 0; trace_det->done_det = 0; trace_det->trace_idx = tridx; trace_det->det_idx = detidx; } static inline void trace_det_clear(trace_det_fglm_mat_t trace_det){ mpz_clear(trace_det->trace_crt); mpz_clear(trace_det->det_crt); mpz_clear(trace_det->trace_num); mpz_clear(trace_det->trace_den); mpz_clear(trace_det->det_num); mpz_clear(trace_det->det_den); mpz_clear(trace_det->tmp); } static inline void crt_lift_trace_det(trace_det_fglm_mat_t trace_det, uint32_t trace_mod, uint32_t det_mod, mpz_t modulus, mpz_t prod, uint32_t prime){ mpz_CRT_ui(trace_det->trace_crt, trace_det->trace_crt, modulus, trace_mod, prime, prod, trace_det->tmp, 1); mpz_CRT_ui(trace_det->det_crt, trace_det->det_crt, modulus, det_mod, prime, prod, trace_det->tmp, 1); } static inline void crt_lift_dense_rows(mpz_t *rows, uint32_t *mod_rows, const uint64_t sz, mpz_t modulus, mpz_t prod, int32_t prime, mpz_t tmp, const int nthrds){ len_t i; for(i = 0; i < sz; i++){ mpz_CRT_ui(rows[i], rows[i], modulus, mod_rows[i], prime, prod, tmp, 1); } } static inline void crt_lift_mat(crt_mpz_matfglm_t mat, sp_matfglm_t *mod_mat, mpz_t modulus, mpz_t prod_crt, const int32_t prime, mpz_t tmp, const int nthrds){ /*assumes prod_crt = modulus * prime */ const uint64_t sz = mat->nrows * mat->ncols; crt_lift_dense_rows(mat->dense_mat, mod_mat->dense_mat, sz, modulus, prod_crt, prime, tmp, nthrds); } static inline void build_mpz_matrix(mpq_matfglm_t mpq_mat, mpz_matfglm_t mpz_mat){ fprintf(stderr, "TODO\n"); } static inline int rat_recon_trace_det(trace_det_fglm_mat_t trace_det, rrec_data_t recdata, mpz_t modulus, mpz_t rnum, mpz_t rden){ int b = ratrecon(rnum, rden, trace_det->trace_crt, modulus, recdata); if(b == 1){ mpz_set(trace_det->trace_num, rnum); mpz_set(trace_det->trace_den, rden); } else { return 0; } b = ratrecon(rnum, rden, trace_det->det_crt, modulus, recdata); if(b == 1){ mpz_set(trace_det->det_num, rnum); mpz_set(trace_det->det_den, rden); } else{ return 0; } return 1; } static inline int check_trace(trace_det_fglm_mat_t trace_det, uint32_t trace_mod, uint32_t prime){ uint32_t lc = mpz_fdiv_ui(trace_det->trace_den, prime); lc = mod_p_inverse_32(lc, prime); uint64_t c = mpz_fdiv_ui(trace_det->trace_num, prime); c *= lc; c = c % prime; return (c == trace_mod); } static inline int check_det(trace_det_fglm_mat_t trace_det, uint32_t det_mod, uint32_t prime){ uint32_t lc = mpz_fdiv_ui(trace_det->det_den, prime); lc = mod_p_inverse_32(lc, prime); uint64_t c = mpz_fdiv_ui(trace_det->det_num, prime); c *= lc; c = c % prime; return (c==det_mod); } #define NEW 1 static inline int64_t rat_recon_dense_rows(mpq_matfglm_t mpq_mat, crt_mpz_matfglm_t crt_mat, mpz_matfglm_t mpz_mat, mpz_t modulus, rrec_data_t rdata, mpz_t rnum, mpz_t rden, long *matrec){ const uint32_t nrows = crt_mat->nrows; const uint32_t ncols = crt_mat->ncols; int64_t cnt = 0; #ifdef NEW mpz_t lcm, coef; mpz_init(lcm); mpz_init(coef); #endif for(uint32_t i = 0; i < nrows; i++){ uint64_t c = i*ncols; #ifdef NEW mpz_set_ui(lcm, 1); #endif for(uint32_t j = 0; j < ncols; j++){ int b = 1; if(*matrec <= c+j){ #ifdef NEW mpz_mul(coef, crt_mat->dense_mat[c+j], lcm); mpz_mod(coef, coef, modulus); b = ratrecon(rnum, rden, coef, modulus, rdata); #else b = ratrecon(rnum, rden, crt_mat->dense_mat[c+j], modulus, rdata); #endif if(b == 1){ mpz_set(mpq_mat->dense_mat[2*c+2*j], rnum); mpz_set(mpq_mat->dense_mat[2*c+2*j+1], rden); mpz_lcm(lcm, lcm, rden); cnt++; } else{ if(cnt > *matrec+1){ fprintf(stderr, "<%.2f%%>", (100*(((double)cnt)/ncols))/nrows ); } *matrec = c; #ifdef NEW mpz_clear(lcm); mpz_clear(coef); #endif return c; } } else{ cnt++; } } } fprintf(stderr, "<100.0%%>\n"); build_mpz_matrix(mpq_mat, mpz_mat); *matrec = cnt; #ifdef NEW mpz_clear(coef); mpz_clear(lcm); #endif return cnt; } void initialize_rrec_data(rrec_data_t recdata){ mpz_init(recdata->r0); mpz_set_ui(recdata->r0, 0); mpz_init(recdata->r1); mpz_set_ui(recdata->r1, 0); mpz_init(recdata->t0); mpz_set_ui(recdata->t0, 0); mpz_init(recdata->t1); mpz_set_ui(recdata->t1, 0); mpz_init(recdata->q); mpz_set_ui(recdata->q, 0); mpz_init(recdata->tmp); mpz_set_ui(recdata->tmp, 0); mpz_init(recdata->N); mpz_set_ui(recdata->N, 0); mpz_init(recdata->D); mpz_set_ui(recdata->D, 0); } void free_rrec_data(rrec_data_t recdata){ mpz_clear(recdata->r0); mpz_clear(recdata->r1); mpz_clear(recdata->t0); mpz_clear(recdata->t1); mpz_clear(recdata->q); mpz_clear(recdata->tmp); mpz_clear(recdata->N); mpz_clear(recdata->D); } msolve-0.6.5/src/msolve/linear.c000066400000000000000000000311641456710632100165530ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ void (*set_linear_poly)(nvars_t nlins, uint32_t *lineqs, nvars_t *linvars, ht_t *bht, int32_t *bexp_lm, bs_t *bs); void (*check_and_set_linear_poly)(nvars_t *nlins_ptr, nvars_t *linvars, uint32_t** lineqs_ptr, ht_t *bht, int32_t *bexp_lm, bs_t *bs); static inline void set_linear_poly_8(nvars_t nlins, uint32_t *lineqs, nvars_t *linvars, ht_t *bht, int32_t *bexp_lm, bs_t *bs){ const int nv = bht->nv; const len_t ebl = bht->ebl; const len_t evl = bht->evl; len_t ctr = 0; exp_t *etmp = (exp_t *)calloc((unsigned long)nv, sizeof(exp_t)); for(long i = 0; i < nlins*((nv + 1)); i++){ lineqs[i] = 0; } /* for(long i = 0; i < nlins*(bht->nv+1); i++){ * lineqs[i] = 0; * } */ int cnt = 0; for(int i = 0; i < nv; i++){ if(linvars[i] != 0){ long len = bs->hm[bs->lmps[linvars[i] - 1]][LENGTH]; const bl_t bi = bs->lmps[linvars[i] - 1]; if(len==bht->nv+1){ for(long j = 0; jcf_8[bs->hm[bi][COEFFS]][j]; lineqs[cnt*(nv+1)+j] = coef; } } else{ hm_t *dt = bs->hm[bi] + OFFSET; for(long j = 0; jcf_8[bs->hm[bi][COEFFS]][j]; exp_t *exp = bht->ev[dt[j]]; /* convert to usual exponent vector without block elimination storage structure */ ctr = 0; for (int k = 1; k < ebl; ++k) { etmp[ctr++] = (int32_t)exp[k]; } for (int k = ebl+1; k < evl; ++k) { etmp[ctr++] = (int32_t)exp[k]; } int isvar = 0; for(int k = 0; k < nv; k++){ if(etmp[k]==1){ lineqs[cnt*(bht->nv+1)+k] = coef; isvar=1; } } if(isvar==0){ lineqs[cnt*(bht->nv+1)+bht->nv] = coef; } } cnt++; } } } free(etmp); } static inline void set_linear_poly_16(nvars_t nlins, uint32_t *lineqs, nvars_t *linvars, ht_t *bht, int32_t *bexp_lm, bs_t *bs){ const int nv = bht->nv; const len_t ebl = bht->ebl; const len_t evl = bht->evl; len_t ctr = 0; exp_t *etmp = (exp_t *)calloc((unsigned long)nv, sizeof(exp_t)); for(long i = 0; i < nlins*((nv + 1)); i++){ lineqs[i] = 0; } /* for(long i = 0; i < nlins*(bht->nv+1); i++){ * lineqs[i] = 0; * } */ int cnt = 0; for(int i = 0; i < nv; i++){ if(linvars[i] != 0){ long len = bs->hm[bs->lmps[linvars[i] - 1]][LENGTH]; const bl_t bi = bs->lmps[linvars[i] - 1]; if(len==bht->nv+1){ for(long j = 0; jcf_16[bs->hm[bi][COEFFS]][j]; lineqs[cnt*(nv+1)+j] = coef; } } else{ hm_t *dt = bs->hm[bi] + OFFSET; for(long j = 0; jcf_16[bs->hm[bi][COEFFS]][j]; exp_t *exp = bht->ev[dt[j]]; /* convert to usual exponent vector without block elimination storage structure */ ctr = 0; for (int k = 1; k < ebl; ++k) { etmp[ctr++] = (int32_t)exp[k]; } for (int k = ebl+1; k < evl; ++k) { etmp[ctr++] = (int32_t)exp[k]; } int isvar = 0; for(int k = 0; k < nv; k++){ if(etmp[k]==1){ lineqs[cnt*(bht->nv+1)+k] = coef; isvar=1; } } if(isvar==0){ lineqs[cnt*(bht->nv+1)+bht->nv] = coef; } } cnt++; } } } free(etmp); } static inline void set_linear_poly_32(nvars_t nlins, uint32_t *lineqs, nvars_t *linvars, ht_t *bht, int32_t *bexp_lm, bs_t *bs){ const int nv = bht->nv; const len_t ebl = bht->ebl; const len_t evl = bht->evl; len_t ctr = 0; exp_t *etmp = (exp_t *)calloc((unsigned long)nv, sizeof(exp_t)); for(long i = 0; i < nlins*((nv + 1)); i++){ lineqs[i] = 0; } /* for(long i = 0; i < nlins*(bht->nv+1); i++){ * lineqs[i] = 0; * } */ int cnt = 0; for(int i = 0; i < nv; i++){ if(linvars[i] != 0){ long len = bs->hm[bs->lmps[linvars[i] - 1]][LENGTH]; const bl_t bi = bs->lmps[linvars[i] - 1]; if(len==bht->nv+1){ for(long j = 0; jcf_32[bs->hm[bi][COEFFS]][j]; lineqs[cnt*(nv+1)+j] = coef; } } else{ hm_t *dt = bs->hm[bi] + OFFSET; for(long j = 0; jcf_32[bs->hm[bi][COEFFS]][j]; exp_t *exp = bht->ev[dt[j]]; /* convert to usual exponent vector without block elimination storage structure */ ctr = 0; for (int k = 1; k < ebl; ++k) { etmp[ctr++] = (int32_t)exp[k]; } for (int k = ebl+1; k < evl; ++k) { etmp[ctr++] = (int32_t)exp[k]; } int isvar = 0; for(int k = 0; k < nv; k++){ if(etmp[k]==1){ lineqs[cnt*(bht->nv+1)+k] = coef; isvar=1; } } if(isvar==0){ lineqs[cnt*(bht->nv+1)+bht->nv] = coef; } } cnt++; } } } free(etmp); } static inline void check_and_set_linear_poly_8(nvars_t *nlins_ptr, nvars_t *linvars, uint32_t** lineqs_ptr, ht_t *bht, int32_t *bexp_lm, bs_t *bs){ long nlins = 0; /* la i-ieme entree de linvars est a 0 si il n'y a pas de forme lineaire dont le terme dominant est vars[i]. Sinon, on met l'indice du polynome dans la base + 1. */ for(long i = 0; i < bs->lml; i++){ long deg = 0; for(int j = 0; j < bht->nv; j++){ deg+=bexp_lm[i*bht->nv+j]; } if(deg == 1){ nlins++; for(int k = 0; k < bht->nv; k++){ if(bexp_lm[i*bht->nv+k] == 1){ linvars[k]=i + 1; } } } } *nlins_ptr = nlins; //On recupere les coefficients des formes lineaires uint32_t* lineqs = calloc(nlins*(bht->nv + 1), sizeof(uint32_t)); int cnt = 0; for(int i = 0; i < bht->nv; i++){ if(linvars[i] != 0){ long len = bs->hm[bs->lmps[linvars[i] - 1]][LENGTH]; const bl_t bi = bs->lmps[linvars[i] - 1]; if(len==bht->nv+1){ for(long j = 0; jcf_8[bs->hm[bi][COEFFS]][j]; lineqs[cnt*(bht->nv+1)+j] = coef; } } else{ hm_t *dt = bs->hm[bi] + OFFSET; for(long j = 0; jcf_8[bs->hm[bi][COEFFS]][j]; exp_t *exp = bht->ev[dt[j]]; int isvar = 0; for(int k = 0; k < bht->nv; k++){ /* exponent vectors in hash table store the degree * at the first position, thus "+1" */ if(exp[k+1]==1){ lineqs[cnt*(bht->nv+1)+k] = coef; isvar=1; } } if(isvar==0){ lineqs[cnt*(bht->nv+1)+bht->nv] = coef; } } cnt++; } } } lineqs_ptr[0] = lineqs; } static inline void check_and_set_linear_poly_16(nvars_t *nlins_ptr, nvars_t *linvars, uint32_t** lineqs_ptr, ht_t *bht, int32_t *bexp_lm, bs_t *bs){ long nlins = 0; /* la i-ieme entree de linvars est a 0 si il n'y a pas de forme lineaire dont le terme dominant est vars[i]. Sinon, on met l'indice du polynome dans la base + 1. */ for(long i = 0; i < bs->lml; i++){ long deg = 0; for(int j = 0; j < bht->nv; j++){ deg+=bexp_lm[i*bht->nv+j]; } if(deg == 1){ nlins++; for(int k = 0; k < bht->nv; k++){ if(bexp_lm[i*bht->nv+k] == 1){ linvars[k]=i + 1; } } } } *nlins_ptr = nlins; //On recupere les coefficients des formes lineaires uint32_t* lineqs = calloc(nlins*(bht->nv + 1), sizeof(uint32_t)); int cnt = 0; for(int i = 0; i < bht->nv; i++){ if(linvars[i] != 0){ long len = bs->hm[bs->lmps[linvars[i] - 1]][LENGTH]; const bl_t bi = bs->lmps[linvars[i] - 1]; if(len==bht->nv+1){ for(long j = 0; jcf_16[bs->hm[bi][COEFFS]][j]; lineqs[cnt*(bht->nv+1)+j] = coef; } } else{ hm_t *dt = bs->hm[bi] + OFFSET; for(long j = 0; jcf_16[bs->hm[bi][COEFFS]][j]; exp_t *exp = bht->ev[dt[j]]; int isvar = 0; for(int k = 0; k < bht->nv; k++){ /* exponent vectors in hash table store the degree * at the first position, thus "+1" */ if(exp[k+1]==1){ lineqs[cnt*(bht->nv+1)+k] = coef; isvar=1; } } if(isvar==0){ lineqs[cnt*(bht->nv+1)+bht->nv] = coef; } } cnt++; } } } lineqs_ptr[0] = lineqs; } static inline void check_and_set_linear_poly_32(nvars_t *nlins_ptr, nvars_t *linvars, uint32_t** lineqs_ptr, ht_t *bht, int32_t *bexp_lm, bs_t *bs){ long nlins = 0; /* la i-ieme entree de linvars est a 0 si il n'y a pas de forme lineaire dont le terme dominant est vars[i]. Sinon, on met l'indice du polynome dans la base + 1. */ for(long i = 0; i < bs->lml; i++){ long deg = 0; for(int j = 0; j < bht->nv; j++){ deg+=bexp_lm[i*bht->nv+j]; } if(deg == 1){ nlins++; for(int k = 0; k < bht->nv; k++){ if(bexp_lm[i*bht->nv+k] == 1){ linvars[k]=i + 1; } } } } *nlins_ptr = nlins; //On recupere les coefficients des formes lineaires uint32_t* lineqs = calloc(nlins*(bht->nv + 1), sizeof(uint32_t)); int cnt = 0; for(int i = 0; i < bht->nv; i++){ if(linvars[i] != 0){ long len = bs->hm[bs->lmps[linvars[i] - 1]][LENGTH]; const bl_t bi = bs->lmps[linvars[i] - 1]; if(len==bht->nv+1){ for(long j = 0; jcf_32[bs->hm[bi][COEFFS]][j]; lineqs[cnt*(bht->nv+1)+j] = coef; } } else{ hm_t *dt = bs->hm[bi] + OFFSET; for(long j = 0; jcf_32[bs->hm[bi][COEFFS]][j]; exp_t *exp = bht->ev[dt[j]]; int isvar = 0; for(int k = 0; k < bht->nv; k++){ /* exponent vectors in hash table store the degree * at the first position, thus "+1" */ if(exp[k+1]==1){ lineqs[cnt*(bht->nv+1)+k] = coef; isvar=1; } } if(isvar==0){ lineqs[cnt*(bht->nv+1)+bht->nv] = coef; } } cnt++; } } } lineqs_ptr[0] = lineqs; } msolve-0.6.5/src/msolve/main.c000066400000000000000000000404131456710632100162220ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "libmsolve.c" #define DEBUGGB 0 #define DEBUGBUILDMATRIX 0 #define IO_DEBUG 0 static inline void display_help(char *str){ fprintf(stdout, "\nmsolve library for polynomial system solving\n"); fprintf(stdout, "implemented by J. Berthomieu, C. Eder, M. Safey El Din\n"); fprintf(stdout, "\n"); /* fprintf(stdout, "commit hash: %s\n\n", GIT_COMMIT_HASH); */ fprintf(stdout, "Basic call:\n"); fprintf(stdout, "\t ./msolve -f [FILE1] -o [FILE2]\n\n"); fprintf(stdout, "FILE1 and FILE2 are respectively the input and output files\n\n"); fprintf(stdout, "Standard options\n\n"); fprintf(stdout, "-f FILE File name (mandatory).\n\n"); fprintf(stdout, "-h Prints this help.\n"); fprintf(stdout, "-o FILE Name of output file.\n"); fprintf(stdout, "-t THR Number of threads to be used.\n"); fprintf(stdout, " Default: 1.\n"); fprintf(stdout, "-v n Level of verbosity, 0 - 2\n"); fprintf(stdout, " 0 - no output (default).\n"); fprintf(stdout, " 1 - global information at the start and\n"); fprintf(stdout, " end of the computation.\n"); fprintf(stdout, " 2 - detailed output for each step of the\n"); fprintf(stdout, " algorithm, e.g. matrix sizes, #pairs, ...\n"); fprintf(stdout, "Input file format:\n"); fprintf(stdout, "\t - first line: variables separated by a comma\n"); fprintf(stdout, "\t - second line: characteristic of the field\n"); fprintf(stdout, "\t - next lines provide the polynomials (one per line),\n"); fprintf(stdout, "\t separated by a comma\n"); fprintf(stdout, "\t (no comma after the final polynomial)\n\n"); fprintf(stdout, "Output file format: \n"); fprintf(stdout, "When there is no solution in an algebraic closure of the base field\n[-1]:\n"); fprintf(stdout, "Where there are infinitely many solutions in \nan algebraic closure of the base field: \n[1, nvars, -1,[]]:\n"); fprintf(stdout,"Else:\n"); fprintf(stdout,"Over prime fields: a rational parametrization of the solutions\n"); fprintf(stdout,"When input coefficients are rational numbers: \nreal solutions to the input system (see the -P flag to recover a parametrization of the solutions)\n"); fprintf(stdout, "See the msolve tutorial for more details (https://msolve.lip6.fr)\n"); fprintf(stdout, "\nAdvanced options:\n\n"); fprintf(stdout, "-F FILE File name encoding parametrizations in binary format.\n\n"); fprintf(stdout, "-g GB Prints reduced Groebner bases of input system for\n"); fprintf(stdout, " first prime characteristic w.r.t. grevlex ordering.\n"); fprintf(stdout, " One element per line is printed, commata separated.\n"); fprintf(stdout, " 0 - Nothing is printed. (default)\n"); fprintf(stdout, " 1 - Leading ideal is printed.\n"); fprintf(stdout, " 2 - Full reduced Groebner basis is printed.\n"); fprintf(stdout, "-c GEN Handling genericity: If the staircase is not generic\n"); fprintf(stdout, " enough, msolve can automatically try to fix this\n"); fprintf(stdout, " situation via first trying a change of the order of\n"); fprintf(stdout, " variables and finally adding a random linear form\n"); fprintf(stdout, " with a new variable (smallest w.r.t. DRL)\n"); fprintf(stdout, " 0 - Nothing is done, msolve quits.\n"); fprintf(stdout, " 1 - Change order of variables.\n"); fprintf(stdout, " 2 - Change order of variables, then try adding a\n"); fprintf(stdout, " random linear form. (default)\n"); fprintf(stdout, "-C Use sparse-FGLM-col algorithm:\n"); fprintf(stdout, " Given an input file with k polynomials\n"); fprintf(stdout, " compute the quotient of the ideal\n"); fprintf(stdout, " generated by the first k-1 polynomials\n"); fprintf(stdout, " with respect to the kth polynomial.\n"); fprintf(stdout, "-e ELIM Define an elimination order: msolve supports two\n"); fprintf(stdout, " blocks, each block using degree reverse lexicographical\n"); fprintf(stdout, " monomial order. ELIM has to be a number between\n"); fprintf(stdout, " 1 and #variables-1. The basis the first block eliminated\n"); fprintf(stdout, " is then computed.\n"); fprintf(stdout, "-I Isolates the real roots (provided some univariate data)\n"); fprintf(stdout, " without re-computing a Gröbner basis\n"); fprintf(stdout, " Default: 0 (no).\n"); fprintf(stdout, "-l LIN Linear algebra variant to be applied:\n"); fprintf(stdout, " 1 - exact sparse / dense\n"); fprintf(stdout, " 2 - exact sparse (default)\n"); fprintf(stdout, " 42 - sparse / dense linearization (probabilistic)\n"); fprintf(stdout, " 44 - sparse linearization (probabilistic)\n"); fprintf(stdout, "-m MPR Maximal number of pairs used per matrix.\n"); fprintf(stdout, " Default: 0 (unlimited).\n"); fprintf(stdout, "-n NF Given n input generators compute normal form of the last NF\n"); fprintf(stdout, " elements of the input w.r.t. a degree reverse lexicographical\n"); fprintf(stdout, " Gröbner basis of the irst (n - NF) input elements.\n"); fprintf(stdout, " At the moment this only works for prime field computations.\n"); fprintf(stdout, " Combining this option with the \"-i\" option assumes that the\n"); fprintf(stdout, " first (n - NF) elements generate already a degree reverse\n"); fprintf(stdout, " lexicographical Gröbner basis.\n"); fprintf(stdout, "-p PRE Precision of the real root isolation.\n"); fprintf(stdout, " Default is 32.\n"); fprintf(stdout, "-P PAR Get also rational parametrization of solution set.\n"); fprintf(stdout, " Default is 0. For a detailed description of the output\n"); fprintf(stdout, " format please see the general output data format section\n"); fprintf(stdout, " above.\n"); fprintf(stdout, "-q Q Uses signature-based algorithms.\n"); fprintf(stdout, " Default: 0 (no).\n"); fprintf(stdout, "-r RED Reduce Groebner basis.\n"); fprintf(stdout, " Default: 1 (yes).\n"); /* fprintf(stdout, "-R Refinement fo real roots.\n"); */ /* fprintf(stdout, " (not implemented yet).\n"); */ fprintf(stdout, "-s HTS Initial hash table size given\n"); fprintf(stdout, " as power of two. Default: 17.\n"); fprintf(stdout, "-S Use f4sat saturation algorithm:\n"); fprintf(stdout, " Given an input file with k polynomials\n"); fprintf(stdout, " compute the saturation of the ideal\n"); fprintf(stdout, " generated by the first k-1 polynomials\n"); fprintf(stdout, " with respect to the kth polynomial.\n"); fprintf(stdout, "-u UHT Number of steps after which the\n"); fprintf(stdout, " hash table is newly generated.\n"); fprintf(stdout, " Default: 0, i.e. no update.\n"); } static void getoptions( int argc, char **argv, int32_t *initial_hts, int32_t *nthreads, int32_t *max_pairs, int32_t *elim_block_len, int32_t *linear_algebra, int32_t *use_signatures, int32_t *update_ht, int32_t *reduce_gb, int32_t *print_gb, int32_t *truncate_lifting, int32_t *genericity_handling, int32_t *saturate, int32_t *colon, int32_t *normal_form, int32_t *normal_form_matrix, int32_t *is_gb, int32_t *get_param, int32_t *precision, int32_t *refine, int32_t *isolate, int32_t *generate_pbm_files, int32_t *info_level, files_gb *files){ int opt, errflag = 0, fflag = 1; char *filename = NULL; char *bin_filename = NULL; char *out_fname = NULL; char *bin_out_fname = NULL; opterr = 1; char options[] = "hf:N:F:v:l:t:e:o:O:u:iI:p:P:q:g:c:s:SCr:R:m:M:n:"; while((opt = getopt(argc, argv, options)) != -1) { switch(opt) { case 'N': *truncate_lifting = strtol(optarg, NULL, 10); break; case 'h': display_help(argv[0]); exit(1); case 'e': *elim_block_len = strtol(optarg, NULL, 10); if (*elim_block_len < 0) { *elim_block_len = 0; } break; case 'u': *update_ht = strtol(optarg, NULL, 10); break; case 'p': *precision = strtol(optarg, NULL, 10); if (*precision < 0) { *precision = 128; } /* if (*precision > 100) { */ /* *precision = 100; */ /* } */ break; case 'q': *use_signatures = strtol(optarg, NULL, 10); if (*use_signatures < 0) { *use_signatures = 0; } if (*use_signatures > 3) { *use_signatures = 0; } break; case 'R': *refine = 1; break; case 'i': *is_gb = 1; break; case 'I': *isolate = strtol(optarg, NULL, 10); break; case 's': *initial_hts = strtol(optarg, NULL, 10); break; case 'S': *saturate = 1; break; case 'C': *colon = 1; break; case 'r': *reduce_gb = strtol(optarg, NULL, 10); break; case 'm': *max_pairs = strtol(optarg, NULL, 10); break; case 'v': *info_level = strtol(optarg, NULL, 10); break; case 't': *nthreads = strtol(optarg, NULL, 10); break; case 'l': *linear_algebra = strtol(optarg, NULL, 10); break; case 'f': fflag = 0; filename = optarg; break; case 'F': fflag = 0; bin_filename = optarg; break; case 'o': out_fname = optarg; break; case 'O': bin_out_fname = optarg; break; case 'P': *get_param = strtol(optarg, NULL, 10); if (*get_param <= 0) { *get_param = 0; } /* if (*get_param > 1) { */ /* *get_param = 1; */ /* } */ break; case 'g': *print_gb = strtol(optarg, NULL, 10); if (*print_gb < 0) { *print_gb = 0; } if (*print_gb > 2) { *print_gb = 2; } break; case 'c': *genericity_handling = strtol(optarg, NULL, 10); if (*genericity_handling < 0) { *genericity_handling = 0; } if (*genericity_handling > 2) { *genericity_handling = 2; } break; case 'n': *normal_form = strtol(optarg, NULL, 10); if (*normal_form < 0) { *normal_form = 0; } break; case 'M': *normal_form_matrix = strtol(optarg, NULL, 10); if (*normal_form_matrix < 0) { *normal_form_matrix = 0; } break; default: errflag++; break; } } if(fflag){ fprintf(stderr,"No given file\n"); display_help(argv[0]); exit(1); } if(errflag){ fprintf(stderr, "Invalid usage\n"); display_help(argv[0]); exit(1); } files->in_file = filename; files->bin_file = bin_filename; files->out_file = out_fname; files->bin_out_file = bin_out_fname; } int main(int argc, char **argv){ /* timinigs */ double st0 = cputime(); double rt0 = realtime(); /** We get values from the command line. **/ int32_t la_option = 2; // by default int32_t use_signatures = 0; int32_t nr_threads = 1; int32_t info_level = 0; int32_t initial_hts = 17; int32_t max_pairs = 0; int32_t elim_block_len = 0; int32_t update_ht = 0; int32_t generate_pbm = 0; int32_t reduce_gb = 1; int32_t print_gb = 0; int32_t truncate_lifting = 0; int32_t genericity_handling = 2; int32_t saturate = 0; int32_t colon = 0; int32_t normal_form = 0; int32_t normal_form_matrix = 0; int32_t is_gb = 0; int32_t get_param = 0; int32_t precision = 128; int32_t refine = 0; /* not used at the moment */ int32_t isolate = 0; /* not used at the moment */ files_gb *files = malloc(sizeof(files_gb)); if(files == NULL) exit(1); files->in_file = NULL; files->bin_file = NULL; files->out_file = NULL; files->bin_out_file = NULL; getoptions(argc, argv, &initial_hts, &nr_threads, &max_pairs, &elim_block_len, &la_option, &use_signatures, &update_ht, &reduce_gb, &print_gb, &truncate_lifting, &genericity_handling, &saturate, &colon, &normal_form, &normal_form_matrix, &is_gb, &get_param, &precision, &refine, &isolate, &generate_pbm, &info_level, files); FILE *fh = fopen(files->in_file, "r"); FILE *bfh = fopen(files->bin_file, "r"); if (fh == NULL && bfh == NULL) { fprintf(stderr, "Input file not found.\n"); exit(1); } if(fh!=NULL){ fclose(fh); } if(bfh != NULL){ fclose(bfh); } fh = NULL; bfh = NULL; /* clear out_file if given */ if(files->out_file != NULL){ FILE *ofile = fopen(files->out_file, "w"); if(ofile == NULL){ fprintf(stderr, "Cannot open output file\n"); exit(1); } fclose(ofile); } /** We get from files the requested data. **/ // int32_t mon_order = 0; int32_t nr_vars = 0; int32_t field_char = 9001; int32_t nr_gens = 0; data_gens_ff_t *gens = allocate_data_gens(); get_data_from_file(files->in_file, &nr_vars, &field_char, &nr_gens, gens); #ifdef IODEBUG display_gens(stdout, gens); #endif gens->rand_linear = 0; gens->random_linear_form = malloc(sizeof(int32_t)*(nr_vars)); gens->elim = elim_block_len; if(0 < field_char && field_char < pow(2, 15) && la_option > 2 && info_level){ fprintf(stderr, "Warning: characteristic is too low for choosing \nprobabilistic linear algebra\n"); fprintf(stderr, "\t linear algebra option set to 2\n"); la_option = 2; } /* data structures for parametrization */ param_t *param = NULL; mpz_param_t *mpz_paramp = malloc(sizeof(mpz_param_t)); mpz_param_init(*mpz_paramp); long nb_real_roots = 0; interval *real_roots = NULL; real_point_t *real_pts = NULL; /* main msolve functionality */ int ret = core_msolve(la_option, use_signatures, nr_threads, info_level, initial_hts, max_pairs, elim_block_len, update_ht, generate_pbm, reduce_gb, print_gb, truncate_lifting, get_param, genericity_handling, saturate, colon, normal_form, normal_form_matrix, is_gb, precision, files, gens, ¶m, mpz_paramp, &nb_real_roots, &real_roots, &real_pts); /* free parametrization */ free(param); mpz_param_clear(*mpz_paramp); if (nb_real_roots > 0) { for(long i = 0; i < nb_real_roots; i++){ real_point_clear(real_pts[i]); mpz_clear(real_roots[i].numer); } free(real_pts); } free(real_roots); /* timings */ if (info_level > 0) { double st1 = cputime(); double rt1 = realtime(); fprintf(stderr, "-------------------------------------------------\ -----------------------------------\n"); fprintf(stderr, "msolve overall time %13.2f sec (elapsed) / %5.2f sec (cpu)\n", rt1-rt0, st1-st0); fprintf(stderr, "-------------------------------------------------\ -----------------------------------\n"); } free_data_gens(gens); free(files); return ret; } msolve-0.6.5/src/msolve/msolve-data.c000066400000000000000000000100121456710632100175020ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ static void initialize_mstrace(mstrace_t msd, md_t *st){ msd->lp = (primes_t *)calloc(st->nthrds, sizeof(primes_t)); /******************* * initialize basis *******************/ msd->bs_qq = initialize_basis(st); /* initialize basis hash table, update hash table, symbolic hash table */ /* msd->bht = initialize_basis_hash_table(st); msd->tht = initialize_secondary_hash_table(msd->bht, st); */ msd->bht = msd->bs_qq->ht; msd->tht = NULL; /* generate array to store modular bases */ msd->bs = (bs_t **)calloc((unsigned long)st->nthrds, sizeof(bs_t *)); msd->bad_primes = calloc((unsigned long)st->nthrds, sizeof(int)); /* initialize tracers */ msd->btrace = (trace_t **)calloc(st->nthrds, sizeof(trace_t *)); msd->btrace[0] = initialize_trace(msd->bs_qq, st); /* initialization of other tracers is done through duplication */ msd->num_gb = (int32_t *)calloc(st->nthrds, sizeof(int32_t)); msd->leadmons_ori = (int32_t **)calloc(st->nthrds, sizeof(int32_t *)); msd->leadmons_current = (int32_t**)calloc(st->nthrds, sizeof(int32_t *)); /* array to store one monomial */ msd->mgb = calloc(msd->bht->nv, sizeof(uint32_t)); msd->blht = (ht_t **)malloc((st->nthrds) * sizeof(ht_t *)); msd->btht = (ht_t **)malloc((st->nthrds) * sizeof(ht_t *)); for(int i = 0; i < st->nthrds; i++){ msd->blht[i] = NULL; msd->btht[i] = NULL; } mpz_init(msd->mod_p); mpz_set_ui(msd->mod_p, 1); mpz_init(msd->prod_p); mpz_set_ui(msd->prod_p, 1); } static void free_mstrace(mstrace_t msd, md_t *st){ free_lucky_primes(&msd->lp); free(msd->lp); /* to be checked if that is to be done when st->ff_bits != 0 This was previously done only when characteristic is zero */ free_basis(&(msd->bs_qq)); free(msd->bs_qq); /*********************************************************** to be checked if that is to be done when st->ff_bits != 0 This was previously done only when characteristic is zero ************************************************************/ /* free_shared_hash_data(msd->bht); if(msd->bht != NULL){ free_hash_table(&(msd->bht)); } */ /***********************************************************/ if(msd->tht!=NULL){ free_hash_table(&(msd->tht)); } free(msd->tht); for(int i = 0; i < st->nthrds; ++i){ if (msd->bs[i] != NULL) { free_basis(&(msd->bs[i])); } } free(msd->bs); free(msd->bad_primes); for(int i = 0; i < st->nthrds; ++i){ if(msd->btrace[i] != NULL){ free_trace(&(msd->btrace[i])); } } free(msd->btrace); free(msd->num_gb); for(int i = 0; i < st->nthrds; ++i){ if(msd->leadmons_ori[i] != NULL){ free(msd->leadmons_ori[i]); } } free(msd->leadmons_ori); for(int i = 0; i < st->nthrds; ++i){ if(msd->leadmons_current[i] != NULL){ free(msd->leadmons_current[i]); } } free(msd->leadmons_current); free(msd->mgb); /* starts at 1 because memory is already cleaned at i = 0 */ for(int i = 1; i < st->nthrds; i++){ if(msd->blht[i] != NULL){ free_hash_table((msd->blht)+i); } } for(int i = 1; i < st->nthrds; i++){ if(msd->btht[i] != NULL){ free_hash_table((msd->btht)+i); } } free(msd->btht); free(msd->blht); mpz_clear(msd->mod_p); mpz_clear(msd->prod_p); } msolve-0.6.5/src/msolve/msolve-data.h000066400000000000000000000206441456710632100175230ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef MSOLVE_DATA_H #define MSOLVE_DATA_H #define _GNU_SOURCE #include "../neogb/data.h" #include #include #include #include #include "../neogb/libneogb.h" #include #define MODP(a,b) \ (a) % (b) typedef struct { mpz_t numer; long k; unsigned int isexact; int sign_left; } interval; typedef len_t nelts_t; typedef int32_t nvars_t; typedef int64_t bits_t; typedef struct{ nvars_t nvars; nvars_t elim; int32_t ngens; int32_t nterms; int32_t field_char; /* counts change of variable orders: * x1 <-> xn * x1 <-> xn-1 * ... * for situation when staircase is not generic enough */ int32_t change_var_order; /* base coefficient for linear form * sum(i^k*x[k]) k = 1, ..., nvars * It is zero if no linear form is active, otherwise != zero. */ int32_t linear_form_base_coef; /* set to 1 if a linear form is chosen randomly */ int32_t rand_linear; int32_t *random_linear_form; char **vnames; int32_t *lens; int32_t *exps; int32_t *cfs; /* int32_t coeffs */ mpz_t **mpz_cfs; /* mpz_t coeffs */ } data_gens_ff_t; typedef uint32_t szmat_t; typedef uint32_t CF_t; typedef uint64_t CF_l_t; typedef uint32_t mod_t; typedef int32_t nvars_t; /* typedef __uint128_t CF_L_t; */ /** M:=Matrix([[0, 1, 0, 0, 0],[ 0, 0, 0, 1, 0],[1, 2, 4, 5, 6],[0, 0, 0, 0, 1],[7, 8, 1, 9, 4]]); Une matrice de la forme 0 1 0 0 0 0 0 0 1 0 1 2 4 5 6 0 0 0 0 1 7 8 1 9 4 est code de la forme ncols = 5 nrows = 2 dense_mat -> 1 2 4 5 6 7 8 1 9 triv_idx -> 0 1 3 (lgr donnee par ncols-nrows) triv_pos -> 1 3 4 dense_idx -> 2 4 (lgr donnee par nrows) **/ typedef struct{ CF_t charac; szmat_t ncols; //dimension du quotient szmat_t nrows; //nbre de lignes non triviales CF_t *dense_mat; // matrice nrows lignes et ncols colonnes (elements donnes par lignes) szmat_t *triv_idx; //tableau d'indices des lignes ne contenant que des 0 et un 1 szmat_t *triv_pos; //position des 1 szmat_t *dense_idx; //position des lignes non triviales (qui constituent donc //dense_mat) szmat_t *dst; //pour la gestion des lignes "denses" mais avec un bloc de zero a la fin } sp_matfglm_t; #ifndef ALIGNED32 #define ALIGNED32 __attribute__((aligned(32))) #endif typedef struct{ CF_t *vecinit ALIGNED32; //vecteur initial CF_t *res ALIGNED32; //va contenir les termes de suites qui nous interessent CF_t *vecmult ALIGNED32; //utilise pour la multiplication CF_t *vvec ALIGNED32; CF_l_t *vec_cache ALIGNED32; //useless mp_limb_t *pts; } fglm_data_t; typedef struct{ nmod_berlekamp_massey_t BMS; nmod_poly_t Z1; nmod_poly_t Z2; nmod_poly_t rZ1; nmod_poly_t rZ2; nmod_poly_t A; nmod_poly_t B; nmod_poly_t V; nmod_poly_t param; nmod_poly_factor_t sqf; } fglm_bms_data_t; typedef struct{ CF_t charac; szmat_t ncols; //dimension du sev du quotient szmat_t nrows; //nbre de lignes non triviales szmat_t nzero; //nbre de lignes nulles CF_t *dense_mat; // matrice nrows lignes et ncols colonnes (elements donnes par lignes) szmat_t *triv_idx; //tableau d'indices des lignes ne contenant que des 0 et un 1 szmat_t *triv_pos; //position des 1 szmat_t *dense_idx; //position des lignes non triviales (qui constituent donc //dense_mat) szmat_t *zero_idx; //tableau d'indices des lignes ne contenant que des 0 szmat_t *dst; //pour la gestion des lignes "denses" mais avec un bloc de zero a la fin } sp_matfglmcol_t; typedef struct{ mp_limb_t charac; nvars_t nvars; nmod_poly_t elim; nmod_poly_t denom; nmod_poly_t *coords; } param_t; typedef struct{ mpz_t r0; mpz_t r1; mpz_t t0; mpz_t t1; mpz_t q; mpz_t tmp; mpz_t N; mpz_t D; } rrec_data_struct_t; typedef rrec_data_struct_t rrec_data_t[1]; typedef struct{ deg_t length; deg_t alloc; mpz_t *coeffs; } mpz_upoly_struct; typedef mpz_upoly_struct mpz_upoly_t[1]; typedef struct{ nvars_t nvars; deg_t nsols; len_t dquot; deg_t dim; mpz_upoly_t elim; mpz_upoly_t denom; mpz_upoly_t *coords; mpz_t *cfs; } mpz_param_struct; typedef mpz_param_struct mpz_param_t[1]; typedef struct{ len_t nb; mpz_param_t *params; } mpz_param_array_struct; typedef mpz_param_array_struct mpz_param_array_t[1]; typedef struct{ uint32_t ncols; /* dimension of quotient */ uint32_t nrows; /* number of non trivial lines */ mpz_t *dense_mat; /*array of nrows*ncols*2 mpz_t coefficients (num, den)*/ uint32_t *triv_idx; /*array of indices of rows which are unit vectors*/ uint32_t *triv_pos; /*position of '1' in unit vectors */ uint32_t *dense_idx; /* array of rows which are NOT unit vectors */ uint32_t *dst; /* blocks of 0's in non-trivial rows */ } mpq_matfglm_struct; typedef mpq_matfglm_struct mpq_matfglm_t[1]; typedef struct{ uint32_t ncols; /* dimension of quotient */ uint32_t nrows; /* number of non trivial lines */ mpz_t *dense_mat; /*array of nrows*ncols mpz_t coefficients*/ mpz_t *denoms; /*denominators for rows which are not unit vectors*/ uint32_t *triv_idx; /*array of indices of rows which are unit vectors*/ uint32_t *triv_pos; /*position of '1' in unit vectors */ uint32_t *dense_idx; /* array of rows which are NOT unit vectors */ uint32_t *dst; /* blocks of 0's in non-trivial rows */ } mpz_matfglm_struct; typedef mpz_matfglm_struct mpz_matfglm_t[1]; typedef struct{ uint32_t ncols; /* dimension of quotient */ uint32_t nrows; /* number of non trivial lines */ mpz_t *dense_mat; /*array of nrows*ncols*2 mpz_t coefficients (num, den)*/ uint32_t *triv_idx; /*array of indices of rows which are unit vectors*/ uint32_t *triv_pos; /*position of '1' in unit vectors */ uint32_t *dense_idx; /* array of rows which are NOT unit vectors */ uint32_t *dst; /* blocks of 0's in non-trivial rows */ } crt_mpz_matfglm_struct; typedef crt_mpz_matfglm_struct crt_mpz_matfglm_t[1]; typedef struct{ uint32_t trace_idx; uint32_t det_idx; mpz_t trace_crt; mpz_t det_crt; mpz_t trace_num; mpz_t trace_den; mpz_t det_num; mpz_t det_den; mpz_t tmp; int16_t done_trace; int16_t done_det; int16_t check_trace; int16_t check_det; } trace_det_fglm_mat_struct; typedef trace_det_fglm_mat_struct trace_det_fglm_mat_t[1]; typedef struct{ mpz_t val_up; mpz_t val_do; deg_t k_up; deg_t k_do; unsigned int isexact; } coord_struct; typedef coord_struct coord_t[1]; typedef struct{ nvars_t nvars; coord_t *coords; } real_point_struct; typedef real_point_struct real_point_t[1]; typedef struct{ char *in_file; char *bin_file; char *out_file; char *bin_out_file; } files_gb; /* data structure for tracing algorithms */ typedef struct{ primes_t *lp; /* array of lucky primes, usually of size st->nthrds */ bs_t *bs_qq; /* basis_qq */ ht_t *bht; /* hash table */ ht_t *tht; /* hash table to store the hashes of the multiples of the basis elements stored in the trace */ bs_t **bs; int *bad_primes; trace_t **btrace; int32_t *num_gb; /* array storing lengths of computed GBs */ int32_t **leadmons_ori; /* original leading monomials (from learning) */ int32_t **leadmons_current; /* leading monomials (from tracing) */ int32_t *mgb; /* array which stores one monomial */ ht_t **blht; ht_t **btht; mpz_t mod_p; mpz_t prod_p; } msolvetrace_data_struct; typedef msolvetrace_data_struct mstrace_t[1]; typedef struct{ int dim; long dquot; int32_t ht_size; /* initial_hts */ int32_t nr_threads; int32_t max_nr_pairs; int32_t elim_block_len; int32_t reset_ht; int32_t la_option; int32_t use_signatures; int32_t info_level; int32_t print_gb; int32_t truncate_lifting; int32_t pbm_file; files_gb *files; } msolveflags_struct; typedef msolveflags_struct msflags_t[1]; #endif msolve-0.6.5/src/msolve/msolve.c000066400000000000000000005245201456710632100166110ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "msolve.h" #include "duplicate.c" #include "linear.c" #include "lifting.c" #include "lifting-gb.c" #define LIFTMATRIX 0 #ifndef MAX #define MAX(a,b) (((a)>(b))?(a):(b)) #endif #ifndef MIN #define MIN(x, y) ((x) > (y) ? (y) : (x)) #endif #define LOG2(X) ((unsigned) (8*sizeof (unsigned long long) - __builtin_clzll((X)) - 1)) #define ilog2_mpz(a) mpz_sizeinbase(a,2) static void mpz_upoly_init(mpz_upoly_t poly, deg_t alloc){ mpz_t *tmp = NULL; if(alloc){ tmp = (mpz_t *)(malloc(alloc * sizeof(mpz_t))); if(tmp==NULL){ fprintf(stderr, "Unable to allocate in mpz_upoly_init\n"); exit(1); } for(deg_t i = 0; i < alloc; i++){ mpz_init(tmp[i]); mpz_set_si(tmp[i], 0); } } poly->coeffs = tmp; poly->alloc = alloc; poly->length = -1; } static void mpz_upoly_init2(mpz_upoly_t poly, deg_t alloc, bits_t nbits){ mpz_t *tmp = NULL; if(alloc){ tmp = (mpz_t *)(malloc(alloc * sizeof(mpz_t))); if(tmp==NULL){ fprintf(stderr, "Unable to allocate in mpz_upoly_init\n"); exit(1); } for(deg_t i = 0; i < alloc; i++){ mpz_init2(tmp[i], nbits); mpz_set_si(tmp[i], 0); } } poly->coeffs = tmp; poly->alloc = alloc; poly->length = -1; } void mpz_upoly_clear(mpz_upoly_t pol){ for(long i = 0; i < pol->alloc; i++){ mpz_clear(pol->coeffs[i]); } free(pol->coeffs); } static inline void mpz_upoly_out_str(FILE *file, mpz_upoly_t pol){ fprintf(file, "["); if(pol->length>0){ fprintf(file, "%d, ", pol->length - 1); //degree fprintf(file, "["); for(long i = 0; i < pol->length - 1; i++){ mpz_out_str(file, 10, pol->coeffs[i]);fprintf(file, ", "); } mpz_out_str(file, 10, pol->coeffs[pol->length - 1]); fprintf(file, "]"); } else{ fprintf(file, "-1, [0]"); } fprintf(file, "]"); } static inline void mpz_param_init(mpz_param_t param){ param->nvars = 0; param->nsols = 0; mpz_upoly_init(param->elim, 0); mpz_upoly_init(param->denom, 0); param->coords=NULL; param->cfs=NULL; } static inline void mpz_param_clear(mpz_param_t param){ mpz_upoly_clear(param->elim); mpz_upoly_clear(param->denom); if(param->coords != NULL){ for(long i = 0; i < param->nvars - 1; i++){ mpz_upoly_clear(param->coords[i]); mpz_clear(param->cfs[i]); } } free(param->coords); free(param->cfs); param->nvars = 0; param->nsols = 0; } static inline void mpz_param_out_str(FILE *file, const data_gens_ff_t *gens, const long dquot, mpz_param_t param, param_t *mod_param){ fprintf(file, "["); fprintf(file, "%d, \n", gens->field_char); /* field charac */ fprintf(file, "%d, \n", param->nvars); //nvars fprintf(file, "%ld, \n", dquot); //dim quotient /* Print all variables: * 1. may include new variable from added linear form, * 2. variables may have a different order than in the. * input system * Both of the above points are due to genericity handling. */ fprintf(file, "["); for (int i = 0; i < param->nvars-1; ++i) { fprintf(file, "'%s', ", gens->vnames[i]); } fprintf(file, "'%s'],\n", gens->vnames[param->nvars-1]); fprintf(file, "["); if(gens->rand_linear){ int32_t sum = 0; if(gens->field_char == 0){ for(int i = 0; i < param->nvars; i++){ sum += abs(gens->random_linear_form[i]) * param->nvars - 1; } } for(int i = 0; i < param->nvars - 1; i++){ fprintf(file, "%d", gens->random_linear_form[i]); if(gens->field_char == 0){ fprintf(file, "/%d", sum); } fprintf(file, ","); } fprintf(file, "%d", gens->random_linear_form[param->nvars-1]); if(gens->field_char == 0){ fprintf(file, "/%d", sum); } } else{ if (gens->linear_form_base_coef > 0) { const int32_t bcf = gens->linear_form_base_coef; for (int i = 0; i < param->nvars-1; ++i) { fprintf(file, "%d,", (int32_t)(pow(i+1, bcf - 1))); } fprintf(file, "%d", (int32_t)(1)); } else{ for (int i = 0; i < param->nvars-1; ++i) { fprintf(file, "%d, ", (int32_t)(0)); } fprintf(file, "%d", (int32_t)(1)); } } fprintf(file, "],\n"); fprintf(file, "[1,\n["); /*at the moment, a single param is returned */ if(gens->field_char){ display_nmod_poly(file, mod_param->elim); } else{ mpz_upoly_out_str(file, param->elim); //elim. poly } fprintf(file, ",\n"); if(gens->field_char){ display_nmod_poly(file, mod_param->denom); } else{ mpz_upoly_out_str(file, param->denom); //denom. poly } fprintf(file, ",\n"); fprintf(file, "[\n"); if(gens->field_char){/* positive characteristic */ if(mod_param->coords != NULL){ for(int i = 0; i < mod_param->nvars - 1; i++){ fprintf(file, "["); if(gens->field_char){ display_nmod_poly(file, mod_param->coords[i]); } if(i == mod_param->nvars - 2){ fprintf(file, "]\n"); } else{ fprintf(file, "],\n"); } } } } else{ if(param->coords != NULL){ for(int i = 0; i < param->nvars - 1; i++){ fprintf(file, "["); mpz_upoly_out_str(file, param->coords[i]); //param. polys fprintf(file, ",\n"); mpz_out_str(file, 10, param->cfs[i]); if(i==param->nvars-2){ fprintf(file, "]\n"); } else{ fprintf(file, "],\n"); } } } } /* fprintf(file, "]"); */ fprintf(file, "]"); fprintf(file, "]]"); } static inline void mpz_param_out_str_maple(FILE *file, const data_gens_ff_t *gens,const long dquot, mpz_param_t param, param_t *mod_param){ mpz_param_out_str(file, gens, dquot, param, mod_param); fprintf(file, "]"); } static inline void display_fglm_crt_matrix(FILE *file, crt_mpz_matfglm_t mat){ fprintf(file, "%u\n", mat->ncols); fprintf(file, "%u\n", mat->nrows); long len1 = (mat->ncols)*(mat->nrows); for(long i = 0; i < len1; i++){ mpz_out_str(file, 10, mat->dense_mat[i]); fprintf(file, " "); } fprintf(file, "\n"); long len2 = (mat->ncols) - (mat->nrows); for(long i = 0; i < len2; i++){ fprintf(file, "%d ", mat->triv_idx[i]); } fprintf(file, "\n"); for(long i = 0; i < len2; i++){ fprintf(file, "%d ", mat->triv_pos[i]); } fprintf(file, "\n"); for(long i = 0; i < mat->nrows; i++){ fprintf(file, "%d ", mat->dense_idx[i]); } fprintf(file, "\n"); } static inline void display_fglm_mpq_matrix(FILE *file, mpq_matfglm_t mat){ fprintf(file, "%u\n", mat->ncols); fprintf(file, "%u\n", mat->nrows); uint64_t nc = mat->ncols; fprintf(file, "["); for(long i = 0; i < mat->nrows; i++){ long c = 2*i*mat->ncols; fprintf(file, "["); for(long j = 0; j < nc-1; j++){ mpz_out_str(file, 10, mat->dense_mat[c+2*j]); fprintf(file, "/"); mpz_out_str(file, 10, mat->dense_mat[c+2*j+1]); fprintf(file, ", "); } mpz_out_str(file, 10, mat->dense_mat[c+2*nc-2]); fprintf(file, "/"); mpz_out_str(file, 10, mat->dense_mat[c+2*nc-1]); fprintf(file, "]\n"); } fprintf(file, "]"); fprintf(file, "\n"); long len2 = (mat->ncols) - (mat->nrows); for(long i = 0; i < len2; i++){ fprintf(file, "%d ", mat->triv_idx[i]); } fprintf(file, "\n"); for(long i = 0; i < len2; i++){ fprintf(file, "%d ", mat->triv_pos[i]); } fprintf(file, "\n"); for(long i = 0; i < mat->nrows; i++){ fprintf(file, "%d ", mat->dense_idx[i]); } fprintf(file, "\n"); } static inline data_gens_ff_t *allocate_data_gens(){ data_gens_ff_t *gens = (data_gens_ff_t *)(malloc(sizeof(data_gens_ff_t))); gens->lens = NULL; gens->exps = NULL; gens->cfs = NULL; gens->mpz_cfs = NULL; gens->random_linear_form = NULL; gens->elim = 0; return gens; } static inline void free_data_gens(data_gens_ff_t *gens){ for(long i = 0; i < gens->nvars; i++){ free(gens->vnames[i]); } free(gens->vnames); if (gens->field_char == 0) { for(long i = 0; i < 2*gens->nterms; i++){ mpz_clear(*(gens->mpz_cfs[i])); free(gens->mpz_cfs[i]); } } free(gens->mpz_cfs); free(gens->lens); free(gens->cfs); free(gens->exps); free(gens->random_linear_form); free(gens); } static inline void display_term(FILE *file, int64_t ind, data_gens_ff_t *gens, int32_t **blen, int32_t *bcf, int32_t **bexp){ if(bcf[ind] != 0 && bcf[ind] != 1){ fprintf(file, "%d", bcf[ind]); display_monomial(file, gens, ind, bexp); } else{ if(bcf[ind] == 1){ int32_t b = display_monomial_single(file, gens, ind, bexp); if(b==0){ fprintf(file, "1"); } } } } static inline void display_basis(FILE *file, int32_t *bld, int32_t **blen, int32_t **bexp, int32_t *bcf, data_gens_ff_t *gens){ int32_t npos = 0; for(int32_t i = 0; i < bld[0]; i++){ int32_t j, end = (*blen)[i]; for(j = 0; j < end; j++){ display_term(file, npos+j, gens, blen, bcf, bexp); if(j < (*blen)[i] - 1){ fprintf(file, "+"); } } // display_term(file, npos+j, gens, blen, bcf, bexp); if(i < bld[0]-1){ fprintf(file, ",\n"); } else{ fprintf(file, "\n"); } npos += (*blen)[i]; } } static inline void display_basis_maple(FILE *file, int32_t *bld, int32_t **blen, int32_t **bexp, int32_t *bcf, data_gens_ff_t *gens){ int32_t npos = 0; fprintf(file, "["); for(int32_t i = 0; i < bld[0]; i++){ int32_t j, end = (*blen)[i]; for(j = 0; j < end; j++){ display_term(file, npos+j, gens, blen, bcf, bexp); if(j < (*blen)[i] - 1){ fprintf(file, "+"); } } // display_term(file, npos+j, gens, blen, bcf, bexp); if(i < bld[0]-1){ fprintf(file, ",\n"); } else{ fprintf(file, "\n"); } npos += (*blen)[i]; } fprintf(file, "]:\n"); } static inline void display_lead_monomials_from_gb(FILE *file, int32_t *bld, int32_t **blen, int32_t **bexp, int32_t *bcf, data_gens_ff_t *gens){ int32_t npos = 0; for(int32_t i = 0; i < bld[0]; i++){ display_term(file, npos, gens, blen, bcf, bexp); if(i < bld[0]-1){ fprintf(file, ",\n"); } else{ fprintf(file, "\n"); } npos += (*blen)[i]; } } static inline void display_monomials_from_array(FILE *file, long length, int32_t *bexp, const int nv, char **vnames){ fprintf(file, "["); for(long i = 0; i < length-1; i++){ display_monomial_full(file, nv, vnames, i, bexp); fprintf(file, ", "); } display_monomial_full(file, nv, vnames, length - 1, bexp); fprintf(file, "]"); } static inline void display_monomials_from_array_maple(FILE *file, long length, int32_t *bexp, const int nv, char **vnames){ fprintf(file, "["); for(long i = 0; i < length-1; i++){ display_monomial_full(file, nv, vnames, i, bexp); fprintf(file, ", "); } display_monomial_full(file, nv, vnames, length - 1, bexp); fprintf(file, "]:"); } /* Used if staircase is not generic enough, before * we add a linear form with a new variable. * * Returns 1 if change of variable order is done, * 0 if all cyclic changes have already been checked * and we should go on to add a linear form with a * new variable. */ static int undo_variable_order_change( data_gens_ff_t *gens ) { int32_t i, j; int32_t len, tmp; char *tmp_char = NULL; const int32_t cvo = gens->change_var_order; const int32_t nvars = gens->nvars; const int32_t ngens = gens->ngens; if (gens->linear_form_base_coef > 0) { return 0; } if (cvo > -1) { /* undo last variable change */ tmp_char = gens->vnames[nvars-1]; gens->vnames[nvars-1] = gens->vnames[cvo]; gens->vnames[cvo] = tmp_char; len = 0; tmp = 0; for (i = 0; i < ngens; ++i) { for (j = 0; j < gens->lens[i]; ++j) { tmp = gens->exps[len + j * nvars + nvars - 1]; gens->exps[len + j * nvars + nvars - 1] = gens->exps[len + j * nvars + cvo]; gens->exps[len + j * nvars + cvo] = tmp; } len += gens->lens[i]*nvars; } } /* all cyclic changes already done, stop here, try to add * a linear form with additional variable afterwards */ gens->change_var_order++; if (gens->change_var_order == nvars-1) { return 0; } else { return 1; } } static int change_variable_order_in_input_system( data_gens_ff_t *gens, int32_t info_level ) { int32_t i, j; int32_t len, tmp; char *tmp_char = NULL; const int32_t cvo = gens->change_var_order; const int32_t nvars = gens->nvars; if (undo_variable_order_change(gens) == 0) { return 0; } /* do the current variable change */ tmp_char = gens->vnames[nvars-1]; gens->vnames[nvars-1] = gens->vnames[cvo+1]; gens->vnames[cvo+1] = tmp_char; len = 0; tmp = 0; for (i = 0; i < gens->ngens; ++i) { for (j = 0; j < gens->lens[i]; ++j) { tmp = gens->exps[len + j * nvars + nvars-1]; gens->exps[len + j * nvars + nvars-1] = gens->exps[len + j * nvars + cvo + 1]; gens->exps[len + j * nvars + cvo + 1] = tmp; } len += gens->lens[i]*nvars; } if (info_level > 0) { printf("\nChanging variable order for possibly more generic staircase:\n"); for(int i = 0; i < nvars-1; i++){ fprintf(stdout, "%s, ", gens->vnames[i]); } fprintf(stdout, "%s\n", gens->vnames[nvars-1]); } return 1; } /* Used if staircase is not generic enough, after * we tried to change variable order. * * Returns 1 if addition of linear form is done, * 0 if an error occurs. */ static int add_linear_form_to_input_system( data_gens_ff_t *gens, int32_t info_level ) { int64_t i, j; int32_t k; int32_t nvars_old, nvars_new; int64_t len_old = 0, len_new; if (gens->linear_form_base_coef == 0) { nvars_old = gens->nvars; nvars_new = nvars_old + 1; for (i = 0; i < gens->ngens; ++i) { len_old += gens->lens[i]; } len_new = len_old + nvars_new; } else { nvars_old = gens->nvars - 1; nvars_new = nvars_old + 1; for (i = 0; i < gens->ngens-1; ++i) { len_old += gens->lens[i]; } len_new = len_old + gens->lens[gens->ngens-1]; } /* for the first run we have to reinitialize gens data with the newly * added variable, then we add the linear form at the end. */ if (gens->linear_form_base_coef == 0) { char *extra_var = (char *)malloc(2*sizeof(char)); strcpy(extra_var, "A"); gens->nvars++; gens->ngens++; gens->lens = realloc(gens->lens, (unsigned long)gens->ngens * sizeof(int32_t)); gens->lens[gens->ngens-1] = (int32_t)nvars_new; /* add new dummy variable (only need for correct freeing of vnames at * the end */ gens->vnames = realloc( gens->vnames, (unsigned long)gens->nvars * sizeof(char *)); gens->vnames[gens->nvars-1] = (char *)malloc(2 * sizeof(char)); gens->vnames[gens->nvars-1] = extra_var; int32_t *old_exps = gens->exps; gens->exps = (int32_t *)calloc( (unsigned long)len_new * nvars_new, sizeof(int32_t)); i = 0; j = 0; while (i < (len_old * nvars_old)) { memcpy(gens->exps+j, old_exps+i, (unsigned long)nvars_old * sizeof(int32_t)); i += nvars_old; j += nvars_new; } free(old_exps); /* add linear form exponents */ while (j < (len_new * nvars_new)) { gens->exps[j] = 1; j += nvars_new+1; } /* allocate memory for coefficients of linear form */ if (gens->field_char > 0) { gens->cfs = realloc(gens->cfs, (unsigned long)len_new * sizeof(int32_t)); } else { gens->mpz_cfs = realloc(gens->mpz_cfs, (unsigned long)2 * len_new * (sizeof(mpz_t *))); for (i = 2*len_old; i < 2*len_new; i += 2) { gens->mpz_cfs[i] = (mpz_t *)malloc(sizeof(mpz_t)); mpz_init(*(gens->mpz_cfs[i])); /* set denominators 1 for all coefficients */ mpz_set_ui(*(gens->mpz_cfs[i]), 1); gens->mpz_cfs[i+1] = (mpz_t *)malloc(sizeof(mpz_t)); mpz_init(*(gens->mpz_cfs[i+1])); /* set denominators 1 for all coefficients */ mpz_set_ui(*(gens->mpz_cfs[i+1]), 1); } } } gens->linear_form_base_coef++; const int32_t bcf = gens->linear_form_base_coef; k = 1; if (info_level > 0) { printf("\nAdding a linear form with an extra variable "); printf("(lowest w.r.t. monomial order)\n"); printf("[coefficients of linear form are k^%d for k looping over variable index 1...n]\n", bcf - 1); } if (gens->field_char > 0) { for (i = len_old; i < len_new - 1; ++i) { gens->cfs[i] = ((int32_t)(pow(k, bcf - 1)) % gens->field_char); k++; } gens->cfs[len_new - 1] = 1; k++; } else { for (i = 2*len_old; i < 2*len_new; i += 2) { mpz_set_ui(*(gens->mpz_cfs[i]), (int32_t)(pow(k, bcf - 1))); k++; } mpz_set_si(*(gens->mpz_cfs[2*(len_new - 1)]), 1); } return 1; } static int add_random_linear_form_to_input_system( data_gens_ff_t *gens, int32_t info_level ) { int64_t i, j; int32_t nvars_old, nvars_new; int64_t len_old = 0, len_new; if (gens->linear_form_base_coef == 0) { nvars_old = gens->nvars; nvars_new = nvars_old + 1; for (i = 0; i < gens->ngens; ++i) { len_old += gens->lens[i]; } len_new = len_old + nvars_new; } else { nvars_old = gens->nvars - 1; nvars_new = nvars_old + 1; for (i = 0; i < gens->ngens-1; ++i) { len_old += gens->lens[i]; } len_new = len_old + gens->lens[gens->ngens-1]; } /* for the first run we have to reinitialize gens data with the newly * added variable, then we add the linear form at the end. */ if (gens->linear_form_base_coef == 0) { char *extra_var = (char *)malloc(2*sizeof(char)); strcpy(extra_var, "A"); gens->nvars++; gens->ngens++; gens->lens = realloc(gens->lens, (unsigned long)gens->ngens * sizeof(int32_t)); gens->lens[gens->ngens-1] = (int32_t)nvars_new; /* add new dummy variable (only need for correct freeing of vnames at * the end */ gens->vnames = realloc( gens->vnames, (unsigned long)gens->nvars * sizeof(char *)); gens->vnames[gens->nvars-1] = (char *)malloc(2 * sizeof(char)); gens->vnames[gens->nvars-1] = extra_var; int32_t *old_exps = gens->exps; gens->exps = (int32_t *)calloc( (unsigned long)len_new * nvars_new, sizeof(int32_t)); i = 0; j = 0; while (i < (len_old * nvars_old)) { memcpy(gens->exps+j, old_exps+i, (unsigned long)nvars_old * sizeof(int32_t)); i += nvars_old; j += nvars_new; } free(old_exps); /* add linear form exponents */ while (j < (len_new * nvars_new)) { gens->exps[j] = 1; j += nvars_new+1; } /* allocate memory for coefficients of linear form */ if (gens->field_char > 0) { gens->cfs = realloc(gens->cfs, (unsigned long)len_new * sizeof(int32_t)); } else { gens->mpz_cfs = realloc(gens->mpz_cfs, (unsigned long)2 * len_new * (sizeof(mpz_t *))); for (i = 2*len_old; i < 2*len_new; i += 2) { gens->mpz_cfs[i] = (mpz_t *)malloc(sizeof(mpz_t)); mpz_init(*(gens->mpz_cfs[i])); gens->mpz_cfs[i+1] = (mpz_t *)malloc(sizeof(mpz_t)); mpz_init(*(gens->mpz_cfs[i+1])); /* set denominators 1 for all coefficients */ mpz_set_ui(*(gens->mpz_cfs[i+1]), 1); } } } gens->linear_form_base_coef++; /* const int32_t bcf = gens->linear_form_base_coef; */ if (info_level > 0) { printf("\nAdding a linear form with an extra variable "); printf("(lowest w.r.t. monomial order)\n"); printf("[coefficients of linear form are randomly chosen]\n"); } srand(time(0)); /* gens->random_linear_form = malloc(sizeof(int32_t)*(nvars_new)); */ gens->random_linear_form = realloc(gens->random_linear_form, sizeof(int32_t)*(nvars_new)); if (gens->field_char > 0) { int j = 0; for (i = len_old; i < len_new; ++i) { gens->random_linear_form[j] = ((int8_t)(rand()) % gens->field_char); while(gens->random_linear_form[j] == 0){ gens->random_linear_form[j] = ((int8_t)(rand()) % gens->field_char); } gens->cfs[i] = gens->random_linear_form[j]; j++; } } else { int j = 0; int32_t sum = 0; for (i = 2*len_old; i < 2*len_new; i += 2) { gens->random_linear_form[j] = ((int8_t)(rand())); while(gens->random_linear_form[j] == 0){ gens->random_linear_form[j] = ((int8_t)(rand())); } if(i < 2*len_new -1){ sum += nvars_old * abs(gens->random_linear_form[j]); } else{ gens->random_linear_form[j] = sum; } mpz_set_si(*(gens->mpz_cfs[i]), gens->random_linear_form[j]); mpz_set_ui(*(gens->mpz_cfs[i+1]), 1); j++; } } gens->rand_linear = 1; return 1; } static inline void nmod_param_out_str(FILE *file, const long dquot, param_t *param){ fprintf(file, "["); fprintf(file, "0, \n"); //charac fprintf(file, "%d, \n", param->nvars); //nvars fprintf(file, "%ld, \n", dquot); //dim quotient display_nmod_poly(file, param->elim); //elim. poly fprintf(file, ",\n"); display_nmod_poly(file, param->denom); //elim. poly fprintf(file, ",\n"); fprintf(file, "[\n"); for(int i = 0; i < param->nvars - 1; i++){ fprintf(file, "["); display_nmod_poly(file, param->coords[i]); //elim. poly fprintf(file, ",\n"); fprintf(file, "[1]"); if(i==param->nvars-2){ fprintf(file, "]\n"); } else{ fprintf(file, "],\n"); } } fprintf(file, "]"); fprintf(file, "]"); } static inline void nmod_param_out_str_maple(FILE *file, const long dquot, param_t *param){ nmod_param_out_str(file, dquot, param); fprintf(file, ":\n"); } static inline void print_msolve_message(FILE * file, int n){ if(n==0){ fprintf(file, "The ideal has positive dimension.\n"); } if(n==1){ fprintf(file, "The staircase of the Grobner basis is not generic enough.\n"); fprintf(file, "\nYou may add to your system a random linear combination of \nthe variables plus a new variable which you choose to be \nthe smallest for the monomial ordering.\n\n"); } } static inline void initialize_mpz_param(mpz_param_t param, param_t *bparam){ param->nvars = bparam->nvars; param->nsols = bparam->elim->length - 1; mpz_upoly_init2(param->elim, bparam->elim->alloc, 2*32*(bparam->elim->length)); mpz_upoly_init2(param->denom, bparam->elim->alloc - 1, 2*32*(bparam->elim->length)); param->elim->length = bparam->elim->length; param->coords = (mpz_upoly_t *)malloc(sizeof(mpz_upoly_t)*(param->nvars - 1)); if(param->coords != NULL){ for(len_t i = 0; i < param->nvars - 1; i++){ mpz_upoly_init(param->coords[i], MAX(1,bparam->elim->alloc - 1)); param->coords[i]->length = bparam->elim->length - 1; } } else{ fprintf(stderr, "Error when initializing parametrization\n"); exit(1); } param->cfs = (mpz_t *)malloc(sizeof(mpz_t) * (param->nvars - 1)); if(param->cfs != NULL){ for(len_t i = 0; i < param->nvars - 1; i++){ mpz_init(param->cfs[i]); mpz_set_ui(param->cfs[i], 1); } } else{ fprintf(stderr, "Error when allocating cfs\n"); exit(1); } } static inline void reduce_generators(mpz_t **tmp, long nterms, int32_t * cfs, int32_t prime){ for(int32_t i = 0; i < 2*nterms; i += 2){ cfs[i/2] = (int32_t)mpz_fdiv_ui(tmp[i][0], prime); } } static inline void check_and_set_linear_poly_non_hashed(long *nlins_ptr, nvars_t *linvars, uint32_t** lineqs_ptr, int32_t *bld, int32_t *bexp_lm, int32_t **blen, int32_t **bexp, int32_t *bcf, long nvars){ long nlins = 0; uint32_t *coefpos = calloc(nvars, sizeof(uint32_t)); uint32_t pos = 0; /* la i-ieme entree de linvars est a 0 si il n'y a pas de forme lineaire dont le terme dominant est vars[i]. Sinon, on met l'indice du polynome dans la base + 1. */ for(long i = 0; i < bld[0]; i++){ long deg = 0; for(int j = 0; j < nvars; j++){ deg+=bexp_lm[i*nvars+j]; } if(deg == 1){ nlins++; for(int k = 0; k < nvars; k++){ if(bexp_lm[i*nvars+k] == 1){ linvars[k] = i + 1; coefpos[k] = pos; } } } pos += (*blen)[i]; } *nlins_ptr = nlins; //On recupere les coefficients des formes lineaires uint32_t* lineqs = calloc(nlins*(nvars + 1), sizeof(uint32_t)); int cnt = 0; for(int i = 0; i < nvars; i++){ if(linvars[i] != 0){ long len = (*blen)[linvars[i] - 1]; if(len==nvars+1){ for(long j = 0; jhm[bi] + OFFSET; for(long j = 0; jcf_32[bs->hm[bi][COEFFS]][j]; int32_t *exp = (*bexp) + (j + coefpos[i]) * nvars; //bht->ev[dt[j]]; int isvar = 0; for(int k = 0; k < nvars; k++){ if(exp[k]==1){ lineqs[cnt*(nvars+1)+k] = coef; isvar=1; } } if(isvar==0){ lineqs[cnt*(nvars+1)+nvars] = coef; } } cnt++; } } } free(coefpos); lineqs_ptr[0] = lineqs; } static inline void check_and_set_vars_squared_in_monomial_basis(nvars_t *squvars, int32_t *lmb, long dquot, long nvars){ /* la i-ieme entree de squvars est a 0 si le monome vars[i]^2 n'est pas dans la base monomiale. Sinon, on met l'indice du monome. De toute facon, en 0, on aurait le monome 1. */ for (deg_t i = 0; i < dquot; i++) { deg_t deg = 0; for (nvars_t j = 0; j < nvars; j++){ deg+=lmb[i*nvars+j]; } if (deg == 2) { for (nvars_t j = 0; j < nvars-1; j++) { if (lmb[i*nvars+j] == 2) { squvars[j]= i; break; } } } } } static inline void normalize_nmod_param(param_t *nmod_param){ if(nmod_param != NULL){ uint32_t prime = nmod_param->charac; uint32_t inv; ulong inv2; n_gcdinv(&inv2, nmod_param->elim->length - 1, prime); inv = inv2 % prime; nmod_poly_fit_length(nmod_param->denom, nmod_param->elim->length - 1); nmod_param->denom->length = nmod_param->elim->length - 1; for(long i = 1; i < nmod_param->elim->length; i++){ nmod_param->denom->coeffs[i-1] = (i * nmod_param->elim->coeffs[i]) % prime; } for(long i = 0; i < nmod_param->elim->length-1; i++){ nmod_param->denom->coeffs[i] = (inv * nmod_param->denom->coeffs[i]) % prime; } for(int j = 0; j < nmod_param->nvars - 1; j++){ nmod_poly_mul(nmod_param->coords[j], nmod_param->coords[j], nmod_param->denom); nmod_poly_rem(nmod_param->coords[j], nmod_param->coords[j], nmod_param->elim); } } } /* On copie nmod_param dans mpz_param On suppose que les allocations ont ete faites via initialize_mpz_param avant. */ static inline void set_mpz_param_nmod(mpz_param_t mpz_param, param_t *nmod_param){ mpz_param->elim->length = nmod_param->elim->length; for(long i = 0; i <= mpz_param->nsols; i++){ mpz_set_ui(mpz_param->elim->coeffs[i], (nmod_param)->elim->coeffs[i]); } mpz_param->elim->length = nmod_param->elim->length; for(long i = 0; i < nmod_param->denom->length; i++){ mpz_set_ui(mpz_param->denom->coeffs[i], nmod_param->denom->coeffs[i]); } mpz_param->denom->length = nmod_param->denom->length; for(int j = 0; j < mpz_param->nvars - 1; j++){ for(long i = 0 ; i < nmod_param->coords[j]->length; i++){ mpz_set_ui(mpz_param->coords[j]->coeffs[i], nmod_param->coords[j]->coeffs[i]); } for(long i = nmod_param->coords[j]->length; i < nmod_param->elim->length - 1; i++){ mpz_set_ui(mpz_param->coords[j]->coeffs[i], 0); } mpz_param->coords[j]->length = nmod_param->elim->length - 1; } } static inline void crt_lift_mpz_upoly(mpz_upoly_t pol, nmod_poly_t nmod_pol, mpz_t modulus, int32_t prime, mpz_t prod, mpz_t tmp, int nthrds){ len_t i; /* #pragma omp parallel for num_threads(nthrds) \ */ /* private(i) schedule(static) */ for(i = 0; i < pol->length; i++){ mpz_CRT_ui(pol->coeffs[i], pol->coeffs[i], modulus, nmod_pol->coeffs[i], prime, prod, tmp, 1); } } /* assumes that all degrees are the same */ static inline void crt_lift_mpz_param(mpz_param_t mpz_param, param_t *nmod_param, mpz_t modulus, mpz_t prod_crt, const int32_t prime, mpz_t tmp, const int nthrds){ /*assumes prod_crt = modulus * prime */ crt_lift_mpz_upoly(mpz_param->elim, nmod_param->elim, modulus, prime, prod_crt, tmp, nthrds); for(len_t i = 0; i < mpz_param->nvars - 1; i++){ crt_lift_mpz_upoly(mpz_param->coords[i], nmod_param->coords[i], modulus, prime, prod_crt, tmp, nthrds); } } /** la sortie est recons / denominator **/ #define RR 1 static inline int rational_reconstruction_mpz_ptr(mpz_t *recons, mpz_t denominator, mpz_t *pol, deg_t len, mpz_t modulus, deg_t *maxrec, mpq_t *coef, mpz_t rnum, mpz_t rden, mpz_t *tmp_num, mpz_t *tmp_den, mpz_t lcm, mpz_t guessed_num, mpz_t guessed_den, rrec_data_t rdata, int info_level){ if(ratrecon(rnum, rden, pol[*maxrec], modulus, rdata) == 0){ return 0; } mpz_set(tmp_num[*maxrec], rnum); mpz_set(tmp_den[*maxrec], rden); for(deg_t i = *maxrec + 1; i < len; i++){ int b = ratrecon(rnum, rden, pol[i], modulus, rdata); if(b == 0){ *maxrec = i - 1; return b; } mpz_set(tmp_num[i], rnum); mpz_set(tmp_den[i], rden); } for(deg_t i = 0; i < *maxrec; i++){ int b = ratrecon(rnum, rden, pol[i], modulus, rdata); if(b == 0){ if(info_level){ fprintf(stderr, "[*]"); } *maxrec = MAX(i-1, 0); return b; } mpz_set(tmp_num[i], rnum); mpz_set(tmp_den[i], rden); } mpz_set(lcm, tmp_den[0]); for(deg_t i = 1; i < len; i++){ mpz_lcm(lcm, lcm, tmp_den[i]); } for(deg_t i = 0; i < len; i++){ mpz_divexact(tmp_den[i], lcm, tmp_den[i]); } for(deg_t i = 0; i < len; i++){ mpz_mul(tmp_num[i], tmp_num[i], tmp_den[i]); } for(deg_t i = 0; i < len; i++){ mpz_set(recons[i], tmp_num[i]); } mpz_set(denominator, lcm); return 1; } static inline int rational_reconstruction_mpz_ptr_with_denom(mpz_t *recons, mpz_t denominator, mpz_t *pol, deg_t len, mpz_t modulus, deg_t *maxrec, mpq_t *coef, mpz_t rnum, mpz_t rden, mpz_t *tmp_num, mpz_t *tmp_den, mpz_t lcm, mpz_t gnum, mpz_t guessed_den, rrec_data_t rdata, int info_level){ mpz_set(gnum, pol[*maxrec]); if(ratreconwden(rnum, rden, gnum, modulus, guessed_den, rdata) == 0){ return 0; } mpz_set(tmp_num[*maxrec], rnum); mpz_set(tmp_den[*maxrec], rden); for(deg_t i = *maxrec + 1; i < len; i++){ mpz_set(gnum, pol[i]); int b = ratreconwden(rnum, rden, gnum, modulus, guessed_den, rdata); if(b == 0){ *maxrec = MAX(0, i - 1); return b; } mpz_set(tmp_num[i], rnum); mpz_set(tmp_den[i], rden); } mpz_set(lcm, tmp_den[*maxrec]); for(deg_t i = *maxrec + 1; i < len; i++){ mpz_lcm(lcm, lcm, tmp_den[i]); } mpz_t newlcm; mpz_init(newlcm); mpz_set(newlcm, lcm); mpz_mul(newlcm, newlcm, guessed_den); mpz_fdiv_q(rdata->D, rdata->D, lcm); mpz_mul(rdata->N, rdata->N, lcm); for(deg_t i = *maxrec-1; i >=0; i--){ mpz_set(gnum, pol[i]); int b = ratreconwden(tmp_num[i], tmp_den[i], gnum, modulus, newlcm, rdata); if(b == 0){ *maxrec = MAX(i + 1, 0); mpz_clear(newlcm); return b; } mpz_divexact(rden, newlcm, guessed_den); mpz_mul(tmp_den[i], tmp_den[i], rden); mpz_lcm(newlcm, newlcm, rden); } mpz_set(lcm, tmp_den[0]); for(deg_t i = 1; i < len; i++){ mpz_lcm(lcm, lcm, tmp_den[i]); } for(deg_t i = 0; i < len; i++){ mpz_divexact(tmp_den[i], lcm, tmp_den[i]); } for(deg_t i = 0; i < len; i++){ mpz_mul(tmp_num[i], tmp_num[i], tmp_den[i]); } for(deg_t i = 0; i < len; i++){ mpz_set(recons[i], tmp_num[i]); } mpz_set(denominator, lcm); mpz_clear(newlcm); return 1; } /** la sortie est recons / denominator **/ static inline int rational_reconstruction_upoly(mpz_upoly_t recons, mpz_t denominator, mpz_upoly_t pol, long len, mpz_t modulus, deg_t *maxrec, mpq_t *coef, mpz_t rnum, mpz_t rden, mpz_upoly_t tmp_num, mpz_upoly_t tmp_den, mpz_t lcm, mpz_t guessed_num, mpz_t guessed_den, rrec_data_t rdata, int info_level){ return rational_reconstruction_mpz_ptr(recons->coeffs, denominator, pol->coeffs, len, modulus, maxrec, coef, rnum, rden, tmp_num->coeffs, tmp_den->coeffs, lcm, guessed_num, guessed_den, rdata, info_level); } static inline int rational_reconstruction_upoly_with_denom(mpz_upoly_t recons, mpz_t denominator, mpz_upoly_t pol, long len, mpz_t modulus, deg_t *maxrec, mpq_t *coef, mpz_t rnum, mpz_t rden, mpz_upoly_t tmp_num, mpz_upoly_t tmp_den, mpz_t lcm, mpz_t guessed_num, mpz_t guessed_den, rrec_data_t rdata, int info_level){ return rational_reconstruction_mpz_ptr_with_denom(recons->coeffs, denominator, pol->coeffs, len, modulus, maxrec, coef, rnum, rden, tmp_num->coeffs, tmp_den->coeffs, lcm, guessed_num, guessed_den, rdata, info_level); } /** returns 0 if rational reconstruction failed **/ static inline int new_rational_reconstruction(mpz_param_t mpz_param, mpz_param_t tmp_mpz_param, param_t *nmod_param, mpq_matfglm_t mpq_mat, crt_mpz_matfglm_t crt_mat, mpz_matfglm_t mpz_mat, trace_det_fglm_mat_t trace_det, sp_matfglm_t *mat, mpz_upoly_t numer, mpz_upoly_t denom, mpz_t modulus, mpz_t prod_crt, int32_t prime, mpq_t *coef, mpz_t rnum, mpz_t rden, rrec_data_t recdata, mpz_t *guessed_num, mpz_t *guessed_den, deg_t *maxrec, uint64_t *matrec, int *is_lifted, int *mat_lifted, int doit, int nthrds, const int info_level){ mpz_mul_ui(prod_crt, modulus, prime); crt_lift_mpz_param(tmp_mpz_param, nmod_param, modulus, prod_crt, prime, trace_det->tmp, nthrds); uint32_t trace_mod = nmod_param->elim->coeffs[trace_det->trace_idx]; uint32_t det_mod = nmod_param->elim->coeffs[trace_det->det_idx]; int b = 1; if(trace_det->done_trace == 0){ b = 0; if(check_trace(trace_det, trace_mod, prime)){ if(trace_det->check_trace == 0){ trace_det->check_trace = 1; } else{ trace_det->done_trace = 1; *maxrec = trace_det->det_idx; } } } if(trace_det->done_det == 0){ b = 0; if(check_det(trace_det, det_mod, prime)){ if(trace_det->check_det == 0){ trace_det->check_det = 1; } else{ trace_det->done_det = 1; *maxrec = trace_det->det_idx; } } } crt_lift_trace_det(trace_det, trace_mod, det_mod, modulus, prod_crt, prime); #if LIFTMATRIX == 1 if(*matrec < crt_mat->nrows*crt_mat->ncols){ crt_lift_mat(crt_mat, mat, modulus, prod_crt, prime, trace_det->tmp, nthrds); } #endif mpz_mul_ui(modulus, modulus, prime); if(doit==0){ return 0; } mpz_fdiv_q_2exp(*guessed_num, modulus, 1); mpz_sqrt(*guessed_num, *guessed_num); mpz_set(*guessed_den, *guessed_num); mpz_set(recdata->N, *guessed_num); mpz_set(recdata->D, *guessed_den); #if LIFTMATRIX == 1 long cnt = 0; if(*matrec < crt_mat->nrows*crt_mat->ncols && *mat_lifted == 0){ cnt = rat_recon_dense_rows(mpq_mat, crt_mat, mpz_mat, modulus, recdata, rnum, rden, matrec); } if(cnt == crt_mat->nrows*crt_mat->ncols || *mat_lifted){ *mat_lifted = 1; } #else *mat_lifted = 1; #endif rat_recon_trace_det(trace_det, recdata, modulus, rnum, rden); if(b && trace_det->done_trace == 1 && trace_det->done_det == 1){ mpz_t denominator; mpz_init(denominator); mpz_t lcm; mpz_init(lcm); int b = 0; if(is_lifted[0]==0){ if(trace_det->done_trace == 1){ mpz_set(*guessed_den, trace_det->trace_den); if(trace_det->done_det == 1){ mpz_lcm(*guessed_den, *guessed_den, trace_det->det_den); } } else{ mpz_set(*guessed_den, trace_det->det_den); if(trace_det->done_trace == 1){ mpz_lcm(*guessed_den, *guessed_den, trace_det->trace_den); } } mpz_fdiv_q(recdata->D, recdata->D, *guessed_den); mpz_mul(recdata->D, recdata->D, recdata->D); mpz_fdiv_q(recdata->N, modulus, recdata->D); mpz_fdiv_q_2exp(recdata->N, recdata->N, 1); mpz_root(recdata->D, modulus, 3); mpz_fdiv_q(recdata->N, modulus, recdata->D); mpz_fdiv_q_2exp(recdata->N, recdata->N, 1); b = rational_reconstruction_upoly_with_denom(mpz_param->elim, denominator, tmp_mpz_param->elim, nmod_param->elim->length, modulus, maxrec, coef, rnum, rden, numer, denom, lcm, *guessed_num, *guessed_den, recdata, info_level); if(b == 0){ mpz_root(recdata->D, modulus, 16); mpz_fdiv_q(recdata->N, modulus, recdata->D); mpz_fdiv_q_2exp(recdata->N, recdata->N, 1); b = rational_reconstruction_upoly_with_denom(mpz_param->elim, denominator, tmp_mpz_param->elim, nmod_param->elim->length, modulus, maxrec, coef, rnum, rden, numer, denom, lcm, *guessed_num, *guessed_den, recdata, info_level); if(b==0){ is_lifted[0] = 0; mpz_clear(denominator); mpz_clear(lcm); return b; } } is_lifted[0] = 1; if(info_level){ fprintf(stderr, "[0]"); } } long nsols = mpz_param->nsols; mpz_t lc; mpz_init(lc); mpz_set(lc, mpz_param->elim->coeffs[nsols]); mpz_mul_ui(lc, lc, nsols); mpq_t c; mpq_init(c); mpz_set_ui(mpq_numref(c), 1); mpz_set_ui(mpq_denref(c), 1); int nc = mpz_param->nvars - 1; mpz_set(*guessed_den, lc); mpz_fdiv_q_2exp(*guessed_num, modulus, 1); mpz_sqrt(recdata->D, *guessed_num); mpz_set(recdata->N, recdata->D); for(int i = 0; i < nc; i++){ *maxrec = MIN(MAX(0, trace_det->det_idx-1), MAX(0,nmod_param->coords[i]->length - 1)); if(is_lifted[0]>0 && is_lifted[i+1]==0){ b = rational_reconstruction_upoly_with_denom(mpz_param->coords[i], denominator, tmp_mpz_param->coords[i], nmod_param->coords[i]->length, modulus, maxrec, coef, rnum, rden, numer, denom, lcm, *guessed_num, *guessed_den, recdata, info_level); if(b == 0){ mpz_set_ui(recdata->D, 1); mpz_mul_2exp(recdata->D, recdata->D, nc); mpz_fdiv_q_2exp(recdata->N, modulus, 1); mpz_fdiv_q(recdata->N, recdata->N, recdata->D); b = rational_reconstruction_upoly_with_denom(mpz_param->coords[i], denominator, tmp_mpz_param->coords[i], nmod_param->coords[i]->length, modulus, maxrec, coef, rnum, rden, numer, denom, lcm, *guessed_num, *guessed_den, recdata, info_level); if(b == 0){ mpz_fdiv_q_2exp(recdata->N, modulus, 1); mpz_root(recdata->D, recdata->N, 16); mpz_fdiv_q(recdata->N, recdata->N, recdata->D); b = rational_reconstruction_upoly_with_denom(mpz_param->coords[i], denominator, tmp_mpz_param->coords[i], nmod_param->coords[i]->length, modulus, maxrec, coef, rnum, rden, numer, denom, lcm, *guessed_num, *guessed_den, recdata, info_level); if(b==0){ mpz_clear(denominator); mpz_clear(lcm); mpz_clear(lc); mpq_clear(c); is_lifted[i+1] = 0; return b; } } } } else{ /* indicates that there is no need to set up below the data as they were already computed */ /* also denominator = 0 by now */ b = 0; } if(info_level && b && is_lifted[i+1] == 0){ fprintf(stderr, "[%d]", i+1); } if(b){ is_lifted[i+1] = 1; mpz_set(mpq_denref(c), denominator); mpq_canonicalize(c); mpz_set(mpz_param->cfs[i], mpq_denref(c)); for(long j = 0; j < mpz_param->coords[i]->length; j++){ mpz_mul(mpz_param->coords[i]->coeffs[j], mpz_param->coords[i]->coeffs[j], mpq_numref(c)); } } } mpz_clear(denominator); mpz_clear(lcm); mpz_clear(lc); mpq_clear(c); return 1; } return 0; } /** on verifie que mpz_pol / lc(mpz_pol) mod prime = nm_pol renvoie 1 si il faut faire le modular check. **/ static inline int check_unit_mpz_nmod_poly(const deg_t len, const mpz_upoly_t mpz_pol, const nmod_poly_t nm_pol, const int32_t prime){ uint32_t lc = mpz_fdiv_ui(mpz_pol->coeffs[len - 1], prime); lc = mod_p_inverse_32(lc, prime); for(deg_t i = 0; i < len; i++){ uint64_t c = mpz_fdiv_ui(mpz_pol->coeffs[i], prime); c *= (uint64_t)lc; c = c % prime; if(c != nm_pol->coeffs[i]){ return i + 1; } } return 0; } static inline int check_param_nmod_poly(const long len, const mpz_upoly_t mpz_pol, const mpz_t den, const mpz_t lcelim, const long nbsol, const nmod_poly_t nm_pol, const int32_t prime){ if(len == 0){ return 0; } mpz_t binv, bprime; mpz_init(binv); mpz_init_set_ui(bprime, prime); mpz_mul(binv, lcelim, den); mpz_mul_ui(binv, binv, nbsol); mpz_invert(binv, binv, bprime); uint32_t inv = mpz_mod_ui(binv, binv, prime); for(long i = 0; i < len; i++){ mpz_mul_ui(binv, mpz_pol->coeffs[i], inv); if(mpz_mod_ui(binv, binv, prime) != (nm_pol->coeffs[i] % prime)){ return 1; } } mpz_clear(binv); mpz_clear(bprime); return 0; } /** renvoie 1 si il faut faire le modular check. **/ static inline int check_param_modular(const mpz_param_t mp_param, const param_t *bparam, const int32_t prime, int *is_lifted, trace_det_fglm_mat_t trace_det, const int info_level){ long len = mp_param->nsols + 1; int c = check_unit_mpz_nmod_poly(len, mp_param->elim, bparam->elim, prime); if(c){ if(info_level){ fprintf(stderr, "<0,%d>", c); } is_lifted[0] = 0; for(int i = 0; invars-1; i++){ is_lifted[i+1] = 0; } trace_det->done_trace = 0; trace_det->check_trace = 0; trace_det->done_det = 0; trace_det->check_det = 0; return 1; } for(int i = 0; i nvars-1; i++ ){ len = mp_param->coords[0]->length; if(check_param_nmod_poly(bparam->coords[i]->length, mp_param->coords[i], mp_param->cfs[i], mp_param->elim->coeffs[mp_param->elim->length - 1], mp_param->elim->length - 1, bparam->coords[i], prime)){ is_lifted[i+1] = 0; if(info_level){ fprintf(stderr, "<%d>", i+1); } return 1; } } return 0; } static inline void get_leading_ideal_information( int32_t *num_gb, int32_t **lead_mons, const int32_t pos, const bs_t * const bs ) { lead_mons[pos] = get_lm_from_bs(bs, bs->ht); num_gb[pos] = bs->lml; } static inline void print_groebner_basis( files_gb *files, const data_gens_ff_t * const gens, const bs_t * const bs, md_t *md, const int32_t fc ) { if(md->print_gb){ int32_t gfc = md->gfc; md->gfc = fc; print_ff_basis_data(files->out_file, "a", bs, bs->ht, md, gens, md->print_gb); md->gfc = gfc; } } static int32_t check_for_single_element_groebner_basis( int *dim, long *dquot_ori, const bs_t * const bs, int32_t **leadmons, const int32_t pos, const md_t * const md ) { int32_t empty_solution_set = 1; int32_t i; if (bs->lml == 1) { if (md->info_level > 0) { fprintf(stdout, "Grobner basis has a single element\n"); } for (i = 0; i < bs->ht->nv; i++) { if (leadmons[pos][i] != 0) { empty_solution_set = 0; break; } } if (empty_solution_set == 1) { *dquot_ori = 0; *dim = 0; if (md->info_level > 0) { fprintf(stdout, "No solution\n"); } } } else { empty_solution_set = 0; } return empty_solution_set; } static int32_t *initial_modular_step( sp_matfglm_t **bmatrix, int32_t **bdiv_xn, int32_t **blen_gb_xn, int32_t **bstart_cf_gb_xn, nvars_t *nlins_ptr, nvars_t *linvars, uint32_t** lineqs_ptr, nvars_t *squvars, fglm_data_t **bdata_fglm, fglm_bms_data_t **bdata_bms, int32_t *num_gb, int32_t **leadmons, uint64_t *bsz, param_t **bparam, bs_t *gbg, md_t *md, const int32_t fc, int print_gb, int *dim, long *dquot_ori, data_gens_ff_t *gens, files_gb *files, int *success) { double rt = realtime(); md->print_gb = print_gb; md->f4_qq_round = 1; int32_t error = 0; int32_t empty_solution_set = 1; bs_t *bs = core_gba(gbg, md, &error, fc); print_tracer_statistics(stdout, rt, md); get_leading_ideal_information(num_gb, leadmons, 0, bs); print_groebner_basis(files, gens, bs, md, fc); empty_solution_set = check_for_single_element_groebner_basis(dim, dquot_ori, bs, leadmons, 0, md); if (empty_solution_set == 1) { return NULL; } check_and_set_linear_poly(nlins_ptr, linvars, lineqs_ptr, bs->ht, leadmons[0], bs); if (has_dimension_zero(bs->lml, bs->ht->nv, leadmons[0])) { long dquot = 0; int32_t *lmb = monomial_basis(bs->lml, bs->ht->nv, leadmons[0], &dquot); if(md->info_level){ fprintf(stderr, "Dimension of quotient: %ld\n", dquot); } if(print_gb==0){ *bmatrix = build_matrixn_from_bs_trace(bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, lmb, dquot, bs, bs->ht, leadmons[0], bs->ht->nv, fc, md->info_level); if(*bmatrix == NULL){ *success = 0; *dim = 0; *dquot_ori = dquot; return NULL; } *bsz = bs->ht->nv - (*nlins_ptr); //nlins ; check_and_set_vars_squared_in_monomial_basis(squvars, lmb, dquot, gens->nvars); *bparam = nmod_fglm_compute_trace_data(*bmatrix, fc, bs->ht->nv, *bsz, *nlins_ptr, linvars, lineqs_ptr[0], squvars, md->info_level, bdata_fglm, bdata_bms, success, md); } free_basis_without_hash_table(&(bs)); *dim = 0; *dquot_ori = dquot; return lmb; } else{ *dim = 1; *dquot_ori = -1; free_basis_without_hash_table(&(bs)); return NULL; } } static void secondary_modular_steps(sp_matfglm_t **bmatrix, int32_t **div_xn, int32_t **len_gb_xn, int32_t **start_cf_gb_xn, nvars_t *bnlins, nvars_t **blinvars, uint32_t **blineqs, nvars_t **bsquvars, fglm_data_t **bdata_fglm, fglm_bms_data_t **bdata_bms, int32_t *num_gb, int32_t **leadmons_ori, int32_t **leadmons_current, uint64_t bsz, param_t **nmod_params, /* trace_t **btrace, */ bs_t *bs_qq, md_t *st, const int32_t fc, int info_level, bs_t **bs, int32_t *lmb_ori, int32_t dquot_ori, primes_t *lp, data_gens_ff_t *gens, double *stf4, const long nbsols, uint32_t *bad_primes) { st->info_level = 0; st->f4_qq_round = 2; double rt = realtime(); /* tracing phase */ len_t i; int32_t error = 0; /* F4 and FGLM are run using a single thread */ /* st->nthrds is reset to its original value afterwards */ const int nthrds = st->nthrds; st->nthrds = 1; for(nvars_t i = 0; i < st->nprimes; i++){ bad_primes[i] = 0; } #pragma omp parallel for num_threads(nthrds) \ private(i) schedule(static) for (i = 0; i < st->nprimes; ++i){ bs[i] = core_gba(bs_qq, st, &error, lp->p[i]); *stf4 = realtime()-rt; /* printf("F4 trace timing %13.2f\n", *stf4); */ if (error > 0) { if (bs[i] != NULL) { free(bs[i]); bs[i] = NULL; } nmod_params[i] = NULL; bad_primes[i] = 1; continue; } int32_t lml = bs[i]->lml; if (st->nev > 0) { int32_t j = 0; for (len_t k = 0; k < bs[i]->lml; ++k) { if (bs[i]->ht->ev[bs[i]->hm[bs[i]->lmps[k]][OFFSET]][0] == 0) { bs[i]->lm[j] = bs[i]->lm[k]; bs[i]->lmps[j] = bs[i]->lmps[k]; ++j; } } lml = j; } if(lml != num_gb[i]){ if (bs[i] != NULL) { free_basis(&(bs[i])); } /* nmod_params[i] = NULL; */ bad_primes[i] = 1; continue; /* return; */ } get_lm_from_bs_trace(bs[i], bs[i]->ht, leadmons_current[i]); if(equal_staircase(leadmons_current[i], leadmons_ori[i], num_gb[i], num_gb[i], bs[i]->ht->nv)){ set_linear_poly(bnlins[i], blineqs[i], blinvars[i], bs[i]->ht, leadmons_current[i], bs[i]); build_matrixn_from_bs_trace_application(bmatrix[i], div_xn[i], len_gb_xn[i], start_cf_gb_xn[i], lmb_ori, dquot_ori, bs[i], bs[i]->ht, leadmons_ori[i], bs[i]->ht->nv, lp->p[i]); if(nmod_fglm_compute_apply_trace_data(bmatrix[i], lp->p[i], nmod_params[i], bs[i]->ht->nv, bsz, bnlins[i], blinvars[i], blineqs[i], bsquvars[i], bdata_fglm[i], bdata_bms[i], nbsols, info_level, st)){ bad_primes[i] = 1; } } else{ bad_primes[i] = 1; } if (bs[i] != NULL) { free_basis_and_only_local_hash_table_data(&(bs[i])); } } st->nthrds = nthrds; } /* sets function pointer */ void set_linear_function_pointer(int32_t fc){ int nbits = 0; if(fc==0){ nbits = 32; } else{ if(fc < pow(2, 8)) { nbits = 8; } else{ if(fc < pow (2, 16)){ nbits = 16; } else nbits = 32; } } switch (nbits) { case 8: set_linear_poly = set_linear_poly_8; check_and_set_linear_poly = check_and_set_linear_poly_8; copy_poly_in_matrix_from_bs = copy_poly_in_matrix_from_bs_8; break; case 16: set_linear_poly = set_linear_poly_16; check_and_set_linear_poly = check_and_set_linear_poly_16; copy_poly_in_matrix_from_bs = copy_poly_in_matrix_from_bs_16; break; case 32: set_linear_poly = set_linear_poly_32; check_and_set_linear_poly = check_and_set_linear_poly_32; copy_poly_in_matrix_from_bs = copy_poly_in_matrix_from_bs_32; break; case 0: set_linear_poly = set_linear_poly_32; check_and_set_linear_poly = check_and_set_linear_poly_32; copy_poly_in_matrix_from_bs = copy_poly_in_matrix_from_bs_32; break; default: set_linear_poly = set_linear_poly_32; check_and_set_linear_poly = check_and_set_linear_poly_32; copy_poly_in_matrix_from_bs = copy_poly_in_matrix_from_bs_32; } } /* - renvoie 0 si le calcul est ok. => GB = [1] dim =0 dquot = 0 => Positive dimension dim > 0 => Dimension zero + calcul qui a pu etre fait. dim=0 dquot > 0 - renvoie 1 si le calcul a echoue => Dimension 0 => pas en position generique - renvoie 2 si besoin de plus de genericite. => (tous les carres ne sont pas sous l'escalier) - renvoie -2 si la carac est > 0 - renvoie -3 si meta data pas bonnes - renvoie -4 si bad prime */ int msolve_trace_qq(mpz_param_t *mpz_paramp, param_t **nmod_param, int *dim_ptr, long *dquot_ptr, data_gens_ff_t *gens, int32_t ht_size, //initial_hts, int32_t nr_threads, int32_t max_nr_pairs, int32_t elim_block_len, int32_t reset_ht, int32_t la_option, int32_t use_signatures, int32_t info_level, int32_t print_gb, int32_t pbm_file, files_gb *files, int round){ const int32_t *lens = gens->lens; const int32_t *exps = gens->exps; uint32_t field_char = gens->field_char; const void *cfs = gens->mpz_cfs; if(gens->field_char){ cfs = gens->cfs; } else{ cfs = gens->mpz_cfs; } int mon_order = 0; int32_t nr_vars = gens->nvars; int32_t nr_gens = gens->ngens; int reduce_gb = 1; int32_t nr_nf = 0; const uint32_t prime_start = pow(2, 30); const int32_t nr_primes = nr_threads; len_t i; /* initialize stuff */ md_t *st = allocate_meta_data(); int *invalid_gens = NULL; int res = validate_input_data(&invalid_gens, cfs, lens, &field_char, &mon_order, &elim_block_len, &nr_vars, &nr_gens, &nr_nf, &ht_size, &nr_threads, &max_nr_pairs, &reset_ht, &la_option, &use_signatures, &reduce_gb, &info_level); /* all data is corrupt */ if (res == -1) { fprintf(stderr, "Invalid input generators, msolve now terminates.\n"); free(invalid_gens); return -3; } /* checks and set all meta data. if a nonzero value is returned then * some of the input data is corrupted. */ if (check_and_set_meta_data_trace(st, lens, exps, cfs, invalid_gens, field_char, mon_order, elim_block_len, nr_vars, nr_gens, nr_nf, ht_size, nr_threads, max_nr_pairs, reset_ht, la_option, use_signatures, reduce_gb, prime_start, nr_primes, pbm_file, info_level)) { free(st); return -3; } /* lucky primes */ primes_t *lp = (primes_t *)calloc(st->nthrds, sizeof(primes_t)); /******************* * initialize basis *******************/ bs_t *bs_qq = initialize_basis(st); /* read in ideal, move coefficients to integers */ import_input_data(bs_qq, st, 0, st->ngens_input, lens, exps, cfs, invalid_gens); free(invalid_gens); invalid_gens = NULL; print_initial_statistics(stderr, st); /* for faster divisibility checks, needs to be done after we have * read some input data for applying heuristics */ calculate_divmask(bs_qq->ht); /* sort initial elements, smallest lead term first */ sort_r(bs_qq->hm, (unsigned long)bs_qq->ld, sizeof(hm_t *), initial_input_cmp, bs_qq->ht); if(gens->field_char == 0){ remove_content_of_initial_basis(bs_qq); /* generate lucky prime numbers */ generate_lucky_primes(lp, bs_qq, st->prime_start, st->nthrds); } else{ lp->old = 0; lp->ld = 1; lp->p = calloc(1, sizeof(uint32_t)); normalize_initial_basis(bs_qq, st->fc); } /* generate array to store modular bases */ bs_t **bs = (bs_t **)malloc((unsigned long)st->nthrds * sizeof(bs_t *)); param_t **nmod_params = (param_t **)malloc((unsigned long)st->nthrds * sizeof(param_t *)); uint32_t *bad_primes = calloc((unsigned long)st->nthrds, sizeof(uint32_t)); /* initialize tracers */ /* trace_t **btrace = (trace_t **)calloc(st->nthrds, sizeof(trace_t *)); btrace[0] = initialize_trace(bs_qq, st); */ /* initialization of other tracers is done through duplication */ uint32_t prime = 0; uint32_t primeinit = 0; uint32_t lprime = 1303905299; srand(time(0)); prime = next_prime(rand() % (1303905301 - (1<<30) + 1) + (1<<30)); while(gens->field_char==0 && is_lucky_prime_ui(prime, bs_qq)){ prime = next_prime(rand() % (1303905301 - (1<<30) + 1) + (1<<30)); } primeinit = prime; lp->p[0] = primeinit; if(gens->field_char){ lp->p[0] = gens->field_char; } sp_matfglm_t **bmatrix = (sp_matfglm_t **)malloc(st->nthrds * sizeof(sp_matfglm_t *)); int32_t **bdiv_xn = (int32_t **)malloc(st->nthrds * sizeof(int32_t *)); int32_t **blen_gb_xn = (int32_t **)malloc(st->nthrds * sizeof(int32_t *)); int32_t **bstart_cf_gb_xn = (int32_t **)malloc(st->nthrds * sizeof(int32_t *)); fglm_data_t **bdata_fglm = (fglm_data_t **)malloc(st->nthrds * sizeof(fglm_data_t *)); fglm_bms_data_t **bdata_bms = (fglm_bms_data_t **)malloc(st->nthrds * sizeof(fglm_bms_data_t *)); int32_t *num_gb = (int32_t *)calloc(st->nthrds, sizeof(int32_t)); int32_t **leadmons_ori = (int32_t **)malloc(st->nthrds * sizeof(int32_t *)); int32_t **leadmons_current = (int32_t**)malloc(st->nthrds * sizeof(int32_t *)); uint64_t bsz = 0; /* data for linear forms */ nvars_t nlins = 0; nvars_t *bnlins = (nvars_t *)calloc(st->nthrds, sizeof(nvars_t)); nvars_t **blinvars = (nvars_t **)malloc(st->nthrds * sizeof(nvars_t *)); nvars_t *linvars = calloc(bs_qq->ht->nv, sizeof(nvars_t)); blinvars[0] = linvars; uint32_t **lineqs_ptr = malloc(st->nthrds * sizeof(uint32_t *)); nvars_t **bsquvars = (nvars_t **) malloc(st->nthrds * sizeof(nvars_t *)); nvars_t *squvars = calloc(nr_vars-1, sizeof(nvars_t)); bsquvars[0] = squvars; set_linear_function_pointer(gens->field_char); int success = 1; int squares = 1; int32_t *lmb_ori = initial_modular_step(bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, &nlins, blinvars[0], lineqs_ptr, squvars, bdata_fglm, bdata_bms, num_gb, leadmons_ori, &bsz, nmod_params, bs_qq, st, lp->p[0], //prime, print_gb, dim_ptr, dquot_ptr, gens, files, &success); if(*dim_ptr == 0 && success && *dquot_ptr > 0 && print_gb == 0){ if(nmod_params[0]->elim->length - 1 != *dquot_ptr){ for(int i = 0; i < nr_vars - 1; i++){ if((squvars[i] == 0) && round ){ squares = 0; success = 0; } } } } (*mpz_paramp)->dim = *dim_ptr; (*mpz_paramp)->dquot = *dquot_ptr; if(lmb_ori == NULL || success == 0 || print_gb || gens->field_char) { free(bs); if(gens->field_char==0){ free_basis(&bs_qq); } //here we should clean nmod_params free_lucky_primes(&lp); free(bad_primes); free(lp); free(linvars); if(nlins){ free(lineqs_ptr[0]); } free(bnlins); free(lineqs_ptr); free(squvars); if(print_gb){ return 0; } if(*dim_ptr == 0 && gens->field_char && success){ /* copy of parametrization */ if(*dquot_ptr != 0){ param_t *par = allocate_fglm_param(gens->field_char, st->nvars); nmod_poly_set(par->elim, nmod_params[0]->elim); nmod_poly_set(par->denom, nmod_params[0]->denom); for(long j = 0; j <= st->nvars - 2; j++){ nmod_poly_set(par->coords[j], nmod_params[0]->coords[j]); } (*nmod_param) = par; } free(st); return 0; } free(st); free(nmod_params); if(*dim_ptr==1){ if(info_level){ fprintf(stderr, "Positive dimensional Grobner basis\n"); } return 0; } if(*dquot_ptr==0){ return 0; } if(*dquot_ptr>0){ if(squares == 0){ return 2; } return 1; } } crt_mpz_matfglm_t crt_mat; mpq_matfglm_t mpq_mat; mpz_matfglm_t mpz_mat; #if LIFTMATRIX == 1 crt_mpz_matfglm_initset(crt_mat, *bmatrix); mpq_matfglm_initset(mpq_mat, *bmatrix); mpz_matfglm_initset(mpz_mat, *bmatrix); #endif /* btrace[0] = st->tr; */ /* duplicate data for multi-threaded multi-mod computation */ duplicate_data_mthread_trace(st->nthrds, bs_qq, st, num_gb, leadmons_ori, leadmons_current, /* btrace, */ bdata_bms, bdata_fglm, bstart_cf_gb_xn, blen_gb_xn, bdiv_xn, bmatrix, nmod_params, nlins, bnlins, blinvars, lineqs_ptr, bsquvars); normalize_nmod_param(nmod_params[0]); if(info_level){ fprintf(stderr, "\nStarts multi-modular computations\n"); } mpz_param_t tmp_mpz_param; mpz_param_init(tmp_mpz_param); initialize_mpz_param(*mpz_paramp, nmod_params[0]); initialize_mpz_param(tmp_mpz_param, nmod_params[0]); //attention les longueurs des mpz_param sont fixees par nmod_params[0] //dans des cas exceptionnels, ca peut augmenter avec un autre premier. /* data for rational reconstruction of trace and det of mult. mat. */ trace_det_fglm_mat_t trace_det; uint32_t detidx = 0; /* int32_t tridx = nmod_params[0]->elim->length-2; */ int32_t tridx = 3* (nmod_params[0]->elim->length - 1) / 4 ; /* tridx = nmod_params[0]->elim->length - 2; */ while(nmod_params[0]->elim->coeffs[tridx] == 0 && tridx > 0){ tridx--; } detidx = 2 * (nmod_params[0]->elim->length - 1) / 3; while(nmod_params[0]->elim->coeffs[detidx] == 0 && detidx < nmod_params[0]->elim->length-2){ detidx++; } trace_det_initset(trace_det, nmod_params[0]->elim->coeffs[tridx], nmod_params[0]->elim->coeffs[detidx], tridx, detidx); /********************************************************************/ mpz_t modulus; mpz_init_set_ui(modulus, primeinit); mpz_t prod_crt; mpz_init_set_ui(prod_crt, primeinit); mpq_t result, test; mpq_init(result); mpq_init(test); mpz_t rnum, rden; /* num and den of reconstructed rationals */ mpz_init(rnum); mpz_set_ui(rnum, 0); mpz_init(rden); mpz_set_ui(rden, 0); set_mpz_param_nmod(tmp_mpz_param, nmod_params[0]); deg_t nsols = tmp_mpz_param->nsols; mpz_upoly_t numer; mpz_upoly_init2(numer, (nsols + 1), 32*(nsols + 1)); numer->length = nsols + 1; mpz_upoly_t denom; mpz_upoly_init2(denom, (nsols + 1), 64*(nsols + 1)); denom->length = nsols + 1; mpz_t guessed_den; mpz_init2(guessed_den, 32*nsols); mpz_set_ui(guessed_den, 1); mpz_t guessed_num; mpz_init2(guessed_num, 32*nsols); mpz_set_ui(guessed_num, 0); deg_t maxrec = 0; uint64_t matrec = 0; int rerun = 1, nprimes = 1, mcheck =1; long nbadprimes = 0; int *is_lifted = malloc(sizeof(int)*nr_vars); for(int i = 0; i < nr_vars; ++i){ is_lifted[i] = 0; } int mat_lifted = 0; int nbdoit = 1; int doit = 1; int prdone = 0; int lpow2 = 1; int clog = 0; int br = 0; rrec_data_t recdata; initialize_rrec_data(recdata); /* measures time spent in rational reconstruction */ double strat = 0; while(rerun == 1 || mcheck == 1){ /* controls call to rational reconstruction */ doit = ((prdone%nbdoit) == 0); /* generate lucky prime numbers */ prime = next_prime(prime); if(prime >= lprime){ prime = next_prime(1<<30); } lp->p[0] = prime; while(is_lucky_prime_ui(prime, bs_qq) || prime==primeinit){ prime = next_prime(prime); if(prime >= lprime){ prime = next_prime(1<<30); } lp->p[0] = prime; } for(len_t i = 1; i < st->nthrds; i++){ prime = next_prime(prime); if(prime >= lprime){ prime = next_prime(1<<30); } lp->p[i] = prime; while(is_lucky_prime_ui(prime, bs_qq) || prime==primeinit){ prime = next_prime(prime); if(prime >= lprime){ prime = next_prime(1<<30); } lp->p[i] = prime; } } prime = lp->p[st->nthrds - 1]; double ca0 = realtime(); double stf4 = 0; secondary_modular_steps(bmatrix, bdiv_xn, blen_gb_xn, bstart_cf_gb_xn, bnlins, blinvars, lineqs_ptr, bsquvars, bdata_fglm, bdata_bms, num_gb, leadmons_ori, leadmons_current, bsz, nmod_params, /* btrace, */ bs_qq, st, field_char, 0, /* info_level, */ bs, lmb_ori, *dquot_ptr, lp, gens, &stf4, nsols, bad_primes); double ca1 = realtime() - ca0; if(nprimes==1){ if(info_level>2){ fprintf(stderr, "------------------------------------------\n"); fprintf(stderr, "#ADDITIONS %13lu\n", (unsigned long)st->application_nr_add * 1000); fprintf(stderr, "#MULTIPLICATIONS %13lu\n", (unsigned long)st->application_nr_mult * 1000); fprintf(stderr, "#REDUCTIONS %13lu\n", (unsigned long)st->application_nr_red); fprintf(stderr, "------------------------------------------\n"); } if(info_level>1){ fprintf(stderr, "Application phase %.2f Gops/sec\n", (st->application_nr_add+st->application_nr_mult)/1000.0/1000.0/(stf4)); fprintf(stderr, "Multi-mod time: GB + fglm (elapsed): %.2f sec\n", (ca1) ); } } for(int i = 0; i < st->nthrds; i++){ if(bad_primes[i] == 0){ normalize_nmod_param(nmod_params[i]); } } /* scrr measures time spent in ratrecon for modular images */ double crr = 0, scrr = 0; /* CRT + rational reconstruction */ for(len_t i = 0; i < st->nthrds; i++){ if(bad_primes[i] == 0){ if(rerun == 0){ mcheck = check_param_modular(*mpz_paramp, nmod_params[i], lp->p[i], is_lifted, trace_det, info_level); } crr = realtime(); if(mcheck==1){ br = new_rational_reconstruction(*mpz_paramp, tmp_mpz_param, nmod_params[i], mpq_mat, crt_mat, mpz_mat, trace_det, bmatrix[i], numer, denom, modulus, prod_crt, lp->p[i], &result, rnum, rden, recdata, &guessed_num, &guessed_den, &maxrec, &matrec, is_lifted, &mat_lifted, doit, st->nthrds, info_level); if(br == 1){ rerun = 0; } else{ rerun = 1; } } scrr += realtime()-crr; nprimes++; } else{ if(info_level){ fprintf(stderr, "\n", lp->p[i]); } nbadprimes++; if(nbadprimes > nprimes){ free(linvars); free(bnlins); free(lineqs_ptr[0]); free(lineqs_ptr); free(squvars); free_rrec_data(recdata); mpz_clear(prod_crt); trace_det_clear(trace_det); free_rrec_data(recdata); fprintf(stderr, "Many other data should be cleaned\n"); return -4; } } } strat += scrr; double t = ((double)nbdoit)*ca1; if((t == 0) || (scrr >= 0.2*t && br == 0)){ nbdoit = 2*nbdoit; lpow2 = 2*nprimes; doit = 0; if(info_level){ fprintf(stderr, "\n",nbdoit,scrr,t); } prdone = 0; } else{ prdone++; } if( (LOG2(nprimes) > clog) || (nbdoit != 1 && (nprimes % (lpow2+1) == 0) ) ){ if(info_level){ fprintf(stderr, "{%d}", nprimes); } clog++; lpow2 = 2*lpow2; } } (*mpz_paramp)->denom->length = (*mpz_paramp)->nsols; for(long i = 1; i <= (*mpz_paramp)->nsols; i++){ mpz_set((*mpz_paramp)->denom->coeffs[i-1], (*mpz_paramp)->elim->coeffs[i]); mpz_mul_ui((*mpz_paramp)->denom->coeffs[i-1], (*mpz_paramp)->denom->coeffs[i-1], i); } if(info_level){ fprintf(stderr, "\n%d primes used\n", nprimes); fprintf(stderr, "Time for CRT + rational reconstruction = %.2f\n", strat); } mpz_param_clear(tmp_mpz_param); mpz_upoly_clear(numer); mpz_upoly_clear(denom); mpz_clear(guessed_num); mpz_clear(guessed_den); mpq_clear(test); mpq_clear(result); mpz_clear(rnum); mpz_clear(rden); mpz_clear(modulus); mpz_clear(prod_crt); free_rrec_data(recdata); trace_det_clear(trace_det); /* free and clean up */ /* free_shared_hash_data(bht); */ /* for(int i = 0; i < st->nthrds; i++){ free_hash_table(blht+i); free_hash_table(btht+i); } */ //here we should clean nmod_params for(i = 0; i < st->nthrds; ++i){ if (bs[i] != NULL) { free_basis(&(bs[i])); } free_fglm_bms_data(bdata_bms[i]); free_fglm_data(bdata_fglm[i]); free(blen_gb_xn[i]); free(bstart_cf_gb_xn[i]); free(bdiv_xn[i]); free(bmatrix[i]->dense_mat); free(bmatrix[i]->dense_idx); free(bmatrix[i]->triv_idx); free(bmatrix[i]->triv_pos); free(bmatrix[i]->dst); free(bmatrix[i]); free(leadmons_ori[i]); free(leadmons_current[i]); /* free_trace(&btrace[i]); */ free(nmod_params[i]); free(blinvars[i]); free(lineqs_ptr[i]); free(bsquvars[i]); } free_basis(&(bs_qq)); free(bs); free(bdata_fglm); free(bdata_bms); free(bmatrix); free(leadmons_ori); free(leadmons_current); free(nmod_params); free_lucky_primes(&lp); free_trace(&(st->tr)); free(st); free(bad_primes); free(bnlins); free(blinvars); free(lineqs_ptr); free(bsquvars); free(is_lifted); free(num_gb); free(blen_gb_xn); free(bstart_cf_gb_xn); free(bdiv_xn); /* free(btrace); */ return 0; } void real_point_init(real_point_t pt, long nvars){ pt->nvars = nvars; pt->coords = malloc(sizeof(coord_t) * nvars); for(long i = 0; i < nvars; i++){ mpz_init(pt->coords[i]->val_up); mpz_init(pt->coords[i]->val_do); pt->coords[i]->k_up = 0; pt->coords[i]->k_do = 0; pt->coords[i]->isexact = 0; } } void real_point_clear(real_point_t pt){ for(long i = 0; i < pt->nvars; i++){ mpz_clear(pt->coords[i]->val_up); mpz_clear(pt->coords[i]->val_do); } free(pt->coords); } void display_real_point(FILE *fstream, real_point_t pt){ fprintf(fstream, "["); for(long i = 0; i < pt->nvars - 1; i++){ fprintf(fstream, "["); mpz_out_str(fstream, 10, pt->coords[i]->val_do); if(pt->coords[i]->k_do && mpz_sgn(pt->coords[i]->val_do)){ fprintf(fstream, " / "); fprintf(fstream, "2"); if(pt->coords[i]->k_do> 1){ fprintf(fstream, "^%d", pt->coords[i]->k_do); } } fprintf(fstream, ", "); mpz_out_str(fstream, 10, pt->coords[i]->val_up); if(pt->coords[i]->k_up && mpz_sgn(pt->coords[i]->val_up)){ fprintf(fstream, " / "); fprintf(fstream, "2"); if(pt->coords[i]->k_up> 1){ fprintf(fstream, "^%d", pt->coords[i]->k_up); } } fprintf(fstream, "], "); } fprintf(fstream, "["); mpz_out_str(fstream, 10, pt->coords[pt->nvars - 1]->val_do); if(pt->coords[pt->nvars - 1]->k_do && mpz_sgn(pt->coords[pt->nvars - 1]->val_do)){ fprintf(fstream, " / "); fprintf(fstream, "2"); if(pt->coords[pt->nvars - 1]->k_do> 1){ fprintf(fstream, "^%d", pt->coords[pt->nvars - 1]->k_do); } } fprintf(fstream, ", "); mpz_out_str(fstream, 10, pt->coords[pt->nvars - 1]->val_up); if(pt->coords[pt->nvars - 1]->k_up && mpz_sgn(pt->coords[pt->nvars - 1]->val_up)){ fprintf(fstream, " / "); fprintf(fstream, "2"); if(pt->coords[pt->nvars - 1]->k_up> 1){ fprintf(fstream, "^%d", pt->coords[pt->nvars - 1]->k_up); } } fprintf(fstream, "]"); fprintf(fstream, "]"); } void display_real_points(FILE *fstream, real_point_t *pts, long nb){ fprintf(fstream, "[1,\n"); /* because at the moment we return a single list */ fprintf(fstream, "["); for(long i = 0; i < nb - 1; i++){ display_real_point(fstream, pts[i]); fprintf(fstream, ", "); } if(nb){ display_real_point(fstream, pts[nb - 1]); } fprintf(fstream, "]\n"); fprintf(fstream, "]"); } void single_exact_real_root_param(mpz_param_t param, interval *rt, long nb, mpz_t *xdo, mpz_t *xup, mpz_t den_up, mpz_t den_do, mpz_t c, mpz_t tmp, mpz_t val_do, mpz_t val_up, mpz_t *tab, real_point_t pt, long prec, int info_level){ mpz_poly_eval_2exp_naive(param->denom->coeffs, param->denom->length - 1, &rt->numer, rt->k, tab, tab + 1); mpz_set(den_up, tab[0]); mpz_set(den_do, tab[0]); for(long nv = 0; nv < param->nvars - 1; nv++){ mpz_poly_eval_2exp_naive(param->coords[nv]->coeffs, param->coords[nv]->length - 1, &rt->numer, rt->k, tab, tab + 1); mpz_set(val_up, tab[0]); mpz_set(val_do, tab[0]); mpz_neg(val_do, val_do); mpz_neg(val_up, val_up); mpz_swap(val_up, val_do); long exp = (rt->k) * ((param->denom->length ) - (param->coords[nv]->length)); mpz_mul_2exp(val_up, val_up, exp + prec); mpz_mul_2exp(val_do, val_do, exp + prec); mpz_mul(tab[1], den_up, param->cfs[nv]); mpz_cdiv_q(val_up, val_up, tab[1]); mpz_fdiv_q(val_do, val_do, tab[1]); mpz_set(pt->coords[nv]->val_up, val_up); mpz_set(pt->coords[nv]->val_do, val_do); pt->coords[nv]->k_up = prec; pt->coords[nv]->k_do = prec; pt->coords[nv]->isexact = 1; } mpz_set(pt->coords[param->nvars - 1]->val_do, rt->numer); mpz_set(pt->coords[param->nvars - 1]->val_up, rt->numer); pt->coords[param->nvars - 1]->k_up = rt->k; pt->coords[param->nvars - 1]->k_do = rt->k; pt->coords[param->nvars - 1]->isexact = 1; } /* assumes b is even */ void generate_table_values(interval *rt, mpz_t c, const long ns, const long b, const long corr, mpz_t *xdo, mpz_t *xup){ mpz_add_ui(c, rt->numer, 1); if(mpz_sgn(rt->numer) >= 0){ mpz_set_ui(xup[0], 1); mpz_set_ui(xdo[0], 1); for(long i = 1; i < ns; i++){ if(i <= b){ mpz_mul(xup[i], xup[i-1], c); mpz_mul(xdo[i], xdo[i-1], rt->numer); } if((i%b)==0 && i > b){ long q = i / b; mpz_mul(xup[i], xup[(q-1)*b], xup[b]); mpz_mul(xdo[i], xdo[(q-1)*b], xdo[b]); } } } else{ mpz_set_ui(xup[0], 1); mpz_set_ui(xdo[0], 1); for(long i = 1; i < ns; i++){ if(i<=b){ if((i & 1) == 1){ mpz_mul(xup[i], xdo[i-1], c); mpz_mul(xdo[i], xup[i-1], rt->numer); } else{ mpz_mul(xup[i], xdo[i-1], rt->numer); mpz_mul(xdo[i], xup[i-1], c); } } if((i%b)==0 && i > b){ long q = i / b; mpz_mul(xup[i], xdo[(q-1)*b], xup[b]); mpz_mul(xdo[i], xup[(q-1)*b], xdo[b]); } } } long q = (ns - 1) / b; for(long i = 1; i <= q; i++){ mpz_mul_2exp(xup[i*b], xup[i*b], corr); mpz_cdiv_q_2exp(xup[i*b], xup[i*b], (rt->k)*i*b); mpz_mul_2exp(xdo[i*b], xdo[i*b], corr); mpz_fdiv_q_2exp(xdo[i*b], xdo[i*b], (rt->k)*i*b); } } /* xdo[i] and xup[i] are rt^i and c^i at precision 2^corr [xdo[i]/2^corr, xup[i]/2^corr] contain [rt^i, c^i] */ void generate_table_values_full(interval *rt, mpz_t c, const long ns, const long b, const long corr, mpz_t *xdo, mpz_t *xup){ mpz_add_ui(c, rt->numer, 1); if(mpz_sgn(rt->numer) >= 0){ mpz_set_ui(xup[0], 1); mpz_set_ui(xdo[0], 1); for(long i = 1; i < ns; i++){ mpz_mul(xup[i], xup[i-1], c); mpz_mul(xdo[i], xdo[i-1], rt->numer); } } else{ mpz_set_ui(xup[0], 1); mpz_set_ui(xdo[0], 1); for(long i = 1; i < ns; i++){ if((i & 1) == 1){ mpz_mul(xup[i], xdo[i-1], c); mpz_mul(xdo[i], xup[i-1], rt->numer); } else{ mpz_mul(xup[i], xdo[i-1], rt->numer); mpz_mul(xdo[i], xup[i-1], c); } } } mpz_mul_2exp(xdo[0], xdo[0], corr); mpz_mul_2exp(xup[0], xup[0], corr); for(long i = 1; i k)*i); mpz_mul_2exp(xdo[i], xdo[i], corr); mpz_fdiv_q_2exp(xdo[i], xdo[i], (rt->k)*i); } } /* quad:=a*x^2+b*x+c; rr1:=r/2^k; rr2:=(r+1)/2^k; numer(expand(subs(x=1/(x+1),subs(x=x*(rr2-rr1),subs(x=x+rr1, quad))))); > numer(subs(x=x+r/2^k, quad)) = (2^k)^2*a*x^2+((2^k)^2*b+2*2^k*a*r)*x+c*(2^k)^2+2^k*b*r+a*r^2 return 1 if quad has real roots in [0, 1] else it returns 0 */ int evalquadric(mpz_t *quad, mpz_t r, long k, mpz_t *tmpquad, mpz_t tmp){ /*We start by computing numer(subs(x=x*(rr2-rr1),subs(x=x+rr1, quad))) */ /* This is */ /*a*x^2+(b*2^k+2*a*r)*x+c*(2^k)^2+2^k*b*r+a*r^2*/ mpz_set(tmpquad[2], quad[2]); mpz_set(tmp, quad[2]); mpz_mul(tmp, tmp, r); /* tmp = a * r */ mpz_set(tmpquad[0], tmp); mpz_mul(tmpquad[0], tmpquad[0], r); /* tmpquad[0] = a*r^2 */ mpz_mul_2exp(tmp, tmp, 1); /* Now tmp = 2*a*r*/ mpz_set(tmpquad[1], quad[1]); mpz_mul_2exp(tmpquad[1], tmpquad[1], k); /*tmpquad[1] = b*2^k*/ mpz_add(tmpquad[1], tmpquad[1], tmp); /* Now tmpquad[1] = 2^k * b + 2 * a * r */ mpz_set(tmp, quad[1]); /*tmp = b*/ mpz_mul(tmp, tmp, r); mpz_mul_2exp(tmp, tmp, k); mpz_add(tmpquad[0], tmpquad[0], tmp); /* tmpquad[0] = 2^k*b*r + a*r^2*/ mpz_set(tmp, quad[0]); mpz_mul_2exp(tmp, tmp, 2*k); /*tmp = c*2^(2k)*/ mpz_add(tmpquad[0], tmpquad[0], tmp); /* At this stage, one has computed tmpquad = numer(subs(x=x*(rr2-rr1),subs(x=x+rr1, quad))) We want to know if it has real roots in [0, 1] */ /* If all coefficients have the same sign, there is no root */ int s=mpz_sgn(tmpquad[0]); if(s==mpz_sgn(tmpquad[1]) && s==mpz_sgn(tmpquad[2])){ return 0; } /* One computes numer(subs(x=1/(x+1)), tmpquad) to apply Descartes*/ /* if tmpquad = a2*x^2+a1*x+a0 computes a0*x^2+(2*a0+a1)*x+a0+a1+a2 */ mpz_add(tmpquad[1], tmpquad[1], tmpquad[0]); mpz_add(tmpquad[2], tmpquad[2], tmpquad[1]); mpz_add(tmpquad[1], tmpquad[1], tmpquad[0]); /* We apply now Descartes */ s=mpz_sgn(tmpquad[0]); if(s==mpz_sgn(tmpquad[1]) && s==mpz_sgn(tmpquad[2])){ return 0; } return 1; } /* evaluates denom (which has degree deg) at the interval [r/2^k, (r+1)/2^k] returns */ int value_denom(mpz_t *denom, long deg, mpz_t r, long k, mpz_t *xdo, mpz_t *xup, mpz_t tmp, mpz_t den_do, mpz_t den_up, long corr, mpz_t c){ /* /\* boo is 1 if den_do and den_up have not the same sign */ /* else it is 0 */ mpz_add_ui(c, r, 1); /* mpz_poly_eval_2exp_naive2(denom, deg, r, k, den_do, tmp); */ /* mpz_poly_eval_2exp_naive2(denom, deg, c, k, den_up, tmp); */ /* if(mpz_sgn(den_do)!=mpz_sgn(den_up)){ */ /* return 1; */ /* } */ /* MODIFS START HERE */ /* if(mpz_cmp(den_do, den_up)>0){ */ /* mpz_swap(den_do, den_up); */ /* } */ /* mpz_mul_2exp(den_do, den_do, corr); */ /* mpz_mul_2exp(den_up, den_up, corr); */ /* mpz_fdiv_q_2exp(den_do, den_do, k*deg); */ /* mpz_cdiv_q_2exp(den_up, den_up, k*deg); */ /* return 0; */ int boo = mpz_poly_eval_interval(denom, deg, k, r, c, tmp, den_do, den_up); if(mpz_cmp(den_do, den_up) > 0){ fprintf(stderr, "BUG (den_do > den_up)\n"); exit(1); } mpz_mul_2exp(den_do, den_do, corr); mpz_mul_2exp(den_up, den_up, corr); mpz_fdiv_q_2exp(den_do, den_do, k*deg); mpz_cdiv_q_2exp(den_up, den_up, k*deg); if(mpz_sgn(den_do)!=mpz_sgn(den_up)){ return 1; } return boo; } int newvalue_denom(mpz_t *denom, long deg, mpz_t r, long k, mpz_t *xdo, mpz_t *xup, mpz_t tmp, mpz_t den_do, mpz_t den_up, long corr, mpz_t c){ mpz_add_ui(c, r, 1); /*boo = 1 if sgn(den_do) != sgn(den_up) else it is 0*/ int boo = mpz_poly_eval_interval(denom, deg, k, r, c, tmp, den_do, den_up); if(mpz_cmp(den_do, den_up) > 0){ fprintf(stderr, "BUG (den_do > den_up)\n"); exit(1); } mpz_mul_2exp(den_do, den_do, corr); mpz_mul_2exp(den_up, den_up, corr); mpz_fdiv_q_2exp(den_do, den_do, k*deg); mpz_cdiv_q_2exp(den_up, den_up, k*deg); return boo; } void lazy_single_real_root_param(mpz_param_t param, mpz_t *polelim, interval *rt, long nb, interval *pos_root, mpz_t *xdo, mpz_t *xup, mpz_t den_up, mpz_t den_do, mpz_t c, mpz_t tmp, mpz_t val_do, mpz_t val_up, mpz_t *tab, real_point_t pt, long prec, long nbits, mpz_t s, int info_level){ long ns = param->nsols ; /* root is exact */ if(rt->isexact==1){ single_exact_real_root_param(param, rt, nb, xdo, xup, den_up, den_do, c, tmp, val_do, val_up, tab, pt, prec, info_level); return ; } long b = 16; long corr = 2*(ns + rt->k); /* checks whether the abs. value of the root is greater than 1 */ generate_table_values_full(rt, c, ns, b, corr, xdo, xup); while(newvalue_denom(param->denom->coeffs, param->denom->length - 1, rt->numer, rt->k, xdo, xup, tmp, den_do, den_up, corr, s)){ /* root is positive */ if(mpz_sgn(rt->numer)>=0){ get_values_at_bounds(param->elim->coeffs, ns, rt, tab); refine_QIR_positive_root(polelim, &ns, rt, tab, 2* (rt->k), info_level); } else{ /* root is positive */ mpz_add_ui(pos_root->numer, rt->numer, 1); mpz_neg(pos_root->numer, pos_root->numer); pos_root->k = rt->k; pos_root->sign_left = - (rt->sign_left); pos_root->isexact = rt->isexact; for(long i = 0; i<=ns; i++){ if((i & 1) == 1){ mpz_neg(polelim[i], polelim[i]); } } get_values_at_bounds(polelim, ns, pos_root, tab); refine_QIR_positive_root(polelim, &ns, pos_root, tab, 2* (pos_root->k) + ns, info_level); for(long i = 0; i<=ns; i++){ if((i & 1) == 1){ mpz_neg(polelim[i], polelim[i]); } } if(pos_root->isexact!=1){ rt->k = pos_root->k; rt->isexact = pos_root->isexact; mpz_add_ui(rt->numer, pos_root->numer, 1); mpz_neg(rt->numer, rt->numer); } else{ rt->k = pos_root->k; if(rt->isexact!=1){ rt->isexact = pos_root->isexact; mpz_set(rt->numer, pos_root->numer); mpz_neg(rt->numer, rt->numer); } } } if(ns != param->nsols){ for(long i = 0; i < param->elim->length; i++){ mpz_set(polelim[i], param->elim->coeffs[i]); } ns = param->nsols; } corr *= 2; b *= 2; generate_table_values_full(rt, c, ns, b, corr, xdo, xup); if(info_level){ fprintf(stderr, "<%ld>", rt->k); } } mpz_t v1, v2; mpz_init(v1); mpz_init(v2); for(long nv = 0; nv < param->nvars - 1; nv++){ mpz_scalar_product_interval(param->coords[nv]->coeffs, param->coords[nv]->length - 1, rt->k, xdo, xup, tmp, val_do, val_up, corr); mpz_neg(val_do, val_do); mpz_neg(val_up, val_up); mpz_swap(val_up, val_do); long dec = prec ; mpz_mul_2exp(val_up, val_up, dec); mpz_mul_2exp(val_do, val_do, dec); if(mpz_cmp(val_do, val_up) > 0){ fprintf(stderr, "BUG in real root extractor(2)\n"); exit(1); } if(mpz_sgn(den_do) >=0 && mpz_sgn(den_up) >= 0){ if(mpz_sgn(val_do)>=0 && mpz_sgn(val_up) >= 0){ mpz_mul(tmp, den_up, param->cfs[nv]); mpz_fdiv_q(v1, val_do, tmp); mpz_mul(tmp, den_do, param->cfs[nv]); mpz_cdiv_q(v2, val_up, tmp); } if(mpz_sgn(val_do)<=0 && mpz_sgn(val_up) >= 0){ mpz_mul(tmp, den_do, param->cfs[nv]); mpz_fdiv_q(v1, val_do, tmp); mpz_cdiv_q(v2, val_up, tmp); } if(mpz_sgn(val_do)<=0 && mpz_sgn(val_up) <= 0){ mpz_mul(tmp, den_do, param->cfs[nv]); mpz_fdiv_q(v1, val_do, tmp); mpz_mul(tmp, den_up, param->cfs[nv]); mpz_cdiv_q(v2, val_up, tmp); } } else{ if(mpz_sgn(val_do)>=0 && mpz_sgn(val_up) >= 0){ mpz_mul(tmp, den_up, param->cfs[nv]); mpz_fdiv_q(v1, val_up, tmp); mpz_mul(tmp, den_do, param->cfs[nv]); mpz_cdiv_q(v2, val_do, tmp); } if(mpz_sgn(val_do)<=0 && mpz_sgn(val_up) >= 0){ mpz_mul(tmp, den_up, param->cfs[nv]); mpz_fdiv_q(v1, val_up, tmp); mpz_cdiv_q(v2, val_do, tmp); } if(mpz_sgn(val_do)<=0 && mpz_sgn(val_up) <= 0){ mpz_mul(tmp, den_do, param->cfs[nv]); mpz_fdiv_q(v1, val_up, tmp); mpz_mul(tmp, den_up, param->cfs[nv]); mpz_cdiv_q(v2, val_do, tmp); } } mpz_set(val_do, v1); mpz_set(val_up, v2); mpz_set(pt->coords[nv]->val_up, val_up); mpz_set(pt->coords[nv]->val_do, val_do); pt->coords[nv]->k_up = prec; pt->coords[nv]->k_do = prec; pt->coords[nv]->isexact = 0; } mpz_set(pt->coords[param->nvars - 1]->val_do, rt->numer); mpz_set(pt->coords[param->nvars - 1]->val_up, rt->numer); mpz_add_ui(pt->coords[param->nvars - 1]->val_up, pt->coords[param->nvars - 1]->val_up, 1); pt->coords[param->nvars - 1]->k_up = rt->k; pt->coords[param->nvars - 1]->k_do = rt->k; pt->coords[param->nvars - 1]->isexact = 0; mpz_clear(v1); mpz_clear(v2); } void normalize_points(real_point_t *pts, int64_t nb, int32_t nv){ for(int64_t i = 0; i < nb; i++){ for(int32_t j = 0; j < nv; j++){ int64_t b = 0; while(mpz_cmp_ui(pts[i]->coords[j]->val_up, 0) !=0 && mpz_divisible_2exp_p(pts[i]->coords[j]->val_up, b + 1) != 0){ b++; } b = MIN(b, pts[i]->coords[j]->k_up); if(b){ mpz_tdiv_q_2exp(pts[i]->coords[j]->val_up, pts[i]->coords[j]->val_up, b); pts[i]->coords[j]->k_up -= b; } b = 0; while(mpz_cmp_ui(pts[i]->coords[j]->val_do, 0) !=0 && mpz_divisible_2exp_p(pts[i]->coords[j]->val_do, b + 1) != 0){ b++; } b = MIN(b, pts[i]->coords[j]->k_do); if(b){ mpz_tdiv_q_2exp(pts[i]->coords[j]->val_do, pts[i]->coords[j]->val_do, b); pts[i]->coords[j]->k_do -= b; } } } } void extract_real_roots_param(mpz_param_t param, interval *roots, long nb, real_point_t *pts, long prec, long nbits, double step, int info_level){ long nsols = param->elim->length - 1; mpz_t *xup = malloc(sizeof(mpz_t)*nsols); mpz_t *xdo = malloc(sizeof(mpz_t)*nsols); mpz_t c, tmp, den_up, den_do, val_up, val_do; mpz_init(c); mpz_init(tmp); mpz_init(den_up); mpz_init(den_do); mpz_init(val_up); mpz_init(val_do); for(long i = 0; i < nsols; i++){ mpz_init_set_ui(xup[i], 1); mpz_init_set_ui(xdo[i], 1); } mpz_t *tab = (mpz_t*)(calloc(8,sizeof(mpz_t)));//table for some intermediate values for(int i=0;i<8;i++){ mpz_init(tab[i]); mpz_set_ui(tab[i], 0); } mpz_t *polelim = calloc(param->elim->length, sizeof(mpz_t)); for(long i = 0; i < param->elim->length; i++){ mpz_init_set(polelim[i], param->elim->coeffs[i]); } interval *pos_root = calloc(1, sizeof(interval)); mpz_init(pos_root->numer); mpz_t s; mpz_init(s); double et = realtime(); for(long nc = 0; nc < nb; nc++){ interval *rt = roots+nc; lazy_single_real_root_param(param, polelim, rt, nb, pos_root, xdo, xup, den_up, den_do, c, tmp, val_do, val_up, tab, pts[nc], prec, nbits, s, info_level); if(info_level){ if(realtime() - et >= step){ fprintf(stderr, "{%.2f%%}", 100*nc/((double) nb)); et = realtime(); } } } for(long i = 0; i < nsols; i++){ mpz_clear(xup[i]); mpz_clear(xdo[i]); } free(xup); free(xdo); mpz_clear(c); mpz_clear(s); mpz_clear(tmp); mpz_clear(den_up); mpz_clear(den_do); mpz_clear(val_up); mpz_clear(val_do); for(int i=0;i<8;i++)mpz_clear(tab[i]); free(tab); for(long i = 0; i < param->elim->length; i++){ mpz_clear(polelim[i]); } free(polelim); mpz_clear(pos_root->numer); free(pos_root); normalize_points(pts, nb, param->nvars); } static real_point_t *isolate_real_roots_param(mpz_param_t param, long *nb_real_roots_ptr, interval **real_roots_ptr, int32_t precision, int32_t nr_threads, int32_t info_level){ mpz_t *pol = malloc(param->elim->length * sizeof(mpz_t)); for(long i = 0; i < param->elim->length; i++){ mpz_init_set(pol[i], param->elim->coeffs[i]); } long maxnbits = mpz_poly_max_bsize_coeffs(param->elim->coeffs, param->elim->length - 1); for(int i = 0; i < param->nvars - 1; i++){ long cmax = mpz_poly_max_bsize_coeffs(param->coords[i]->coeffs, param->coords[i]->length - 1); maxnbits = MAX(cmax, maxnbits); } long prec = MAX(precision, 128 + (maxnbits) / 32 ); double st = realtime(); long unsigned int nbpos = 0; long unsigned int nbneg = 0; interval *roots = real_roots(pol, param->elim->length - 1, &nbpos, &nbneg, prec, nr_threads, info_level ); long nb = nbpos + nbneg; double step = (realtime() - st) / (nb) * 10 * LOG2(precision); real_point_t *pts = NULL; if(info_level > 0){ fprintf(stderr, "Number of real roots: %ld\n", nb); } if(nb){ /* */ if(info_level){ fprintf(stderr, "Starts real root extraction.\n"); } double st = realtime(); pts = malloc(sizeof(real_point_t) * nb); for(long i = 0; i < nb; i++){ real_point_init(pts[i], param->nvars); } extract_real_roots_param(param, roots, nb, pts, precision, maxnbits, step, info_level); if(info_level){ fprintf(stderr, "Elapsed time (real root extraction) = %.2f\n", realtime() - st); } } *real_roots_ptr = roots; *nb_real_roots_ptr = nb; for(long i = 0; i < param->elim->length; i++){ mpz_clear(pol[i]); } free(pol); return pts; } void isolate_real_roots_lparam(mpz_param_array_t lparams, long **lnbr_ptr, interval ***lreal_roots_ptr, real_point_t ***lreal_pts_ptr, int32_t precision, int32_t nr_threads, int32_t info_level){ long *lnbr = malloc(sizeof(long) * lparams->nb); interval **lreal_roots = malloc(sizeof(interval *) * lparams->nb); real_point_t **lreal_pts = malloc(sizeof(real_point_t *) * lparams->nb); for(int i = 0; i < lparams->nb; i++){ lreal_roots[i] = NULL; lreal_pts[i] = NULL; } for(int i = 0; i < lparams->nb; i++){ lreal_pts[i] = isolate_real_roots_param(lparams->params[i], lnbr + i, lreal_roots + i, precision, nr_threads, info_level); } (*lnbr_ptr) = lnbr; (*lreal_roots_ptr) = lreal_roots; (*lreal_pts_ptr) = lreal_pts; } int real_msolve_qq(mpz_param_t *mpz_paramp, param_t **nmod_param, int *dim_ptr, long *dquot_ptr, long *nb_real_roots_ptr, interval **real_roots_ptr, real_point_t **real_pts_ptr, data_gens_ff_t *gens, int32_t ht_size, //initial_hts, int32_t nr_threads, int32_t max_nr_pairs, int32_t elim_block_len, int32_t reset_ht, int32_t la_option, int32_t use_signatures, int32_t info_level, int32_t print_gb, int32_t pbm_file, int32_t precision, files_gb *files, int round, int32_t get_param){ /* 0 is comp. is ok 1 if comp. failed 2 if more genericity is required -2 if charac is > 0 -3 if meta data are corrupted -4 if bad prime */ double ct0 = cputime(); double rt0 = realtime(); int b = msolve_trace_qq(mpz_paramp, nmod_param, dim_ptr, dquot_ptr, gens, ht_size, //initial_hts, nr_threads, max_nr_pairs, elim_block_len, reset_ht, la_option, use_signatures, info_level, print_gb, pbm_file, files, round); double ct1 = cputime(); double rt1 = realtime(); if(info_level && print_gb == 0){ fprintf(stderr, "Time for rational param: %13.2f (elapsed) sec / %5.2f sec (cpu)\n\n", rt1 - rt0, ct1 - ct0); } if(get_param>1){ return b; } if(print_gb){ return 0; } real_point_t *pts = NULL; if(b==0 && *dim_ptr == 0 && *dquot_ptr > 0 && gens->field_char == 0){ pts = isolate_real_roots_param(*mpz_paramp, nb_real_roots_ptr, real_roots_ptr, precision, nr_threads, info_level); int32_t nb = *nb_real_roots_ptr; if(nb){ /* If we added a linear form for genericity reasons remove do not * return the last (new) variable in the solutions later on */ if (gens->linear_form_base_coef > 0) { for (long i = 0; i < nb; ++i) { pts[i]->nvars--; } } /* If we changed the variable order for genericity reasons we have * to rechange the entries in the solution points. */ /* This is to be done only when the parametrization is not requested */ if (get_param == 0 && gens->change_var_order != -1 && gens->change_var_order != (*mpz_paramp)->nvars-1 && gens->linear_form_base_coef == 0) { coord_t *tmp = malloc(sizeof(coord_t)); const int32_t nvars = gens->nvars; int32_t lidx = gens->change_var_order; for (long i = 0; i < nb; ++i) { memcpy(tmp, pts[i]->coords[nvars - 1], sizeof(coord_t)); memcpy(pts[i]->coords[nvars - 1], pts[i]->coords[lidx], sizeof(coord_t)); memcpy(pts[i]->coords[lidx], tmp, sizeof(coord_t)); } free(tmp); } *real_pts_ptr = pts; } } return b; } void display_arrays_of_real_roots(files_gb *files, int32_t len, real_point_t **lreal_pts, long *lnbr){ if(files->out_file != NULL){ FILE *ofile = fopen(files->out_file, "a+"); fprintf(ofile, "["); for(int i = 0; i < len - 1; i++){ display_real_points(ofile, lreal_pts[i], lnbr[i]); fprintf(ofile, ", \n"); } display_real_points(ofile, lreal_pts[len - 1], lnbr[len - 1]); fprintf(ofile, "];\n"); fclose(ofile); } else{ fprintf(stdout, "["); for(int i = 0; i < len - 1; i++){ display_real_points(stdout, lreal_pts[i], lnbr[i]); fprintf(stdout, ", \n"); } display_real_points(stdout, lreal_pts[len - 1], lnbr[len - 1]); fprintf(stdout, "];\n"); } } void display_output(int b, int dim, int dquot, files_gb *files, data_gens_ff_t *gens, param_t *param, mpz_param_t *mpz_paramp, int get_param, long *nb_real_roots_ptr, interval **real_roots_ptr, real_point_t **real_pts_ptr, int info_level){ if(dquot == 0){ if(files->out_file != NULL){ FILE *ofile = fopen(files->out_file, "a+"); fprintf(ofile, "[-1]:\n"); fclose(ofile); } else{ fprintf(stdout, "[-1]:\n"); } return; } if(dim == 0 && dquot >= 0){ (*mpz_paramp)->nvars = gens->nvars; if(files->out_file != NULL){ FILE *ofile = fopen(files->out_file, "a+"); fprintf(ofile, "[0, "); if (get_param >= 1 || gens->field_char) { mpz_param_out_str_maple(ofile, gens, dquot, *mpz_paramp, param); } if(get_param <= 1 && gens->field_char == 0){ if(get_param){ fprintf(ofile, ","); } display_real_points( ofile, *real_pts_ptr, *nb_real_roots_ptr); } fprintf(ofile, "]:\n"); fclose(ofile); } else{ fprintf(stdout, "[0, "); if (get_param >= 1 || gens->field_char) { mpz_param_out_str_maple(stdout, gens, dquot, *mpz_paramp, param); } if(get_param <= 1 && gens->field_char == 0){ if(get_param){ fprintf(stdout, ","); } display_real_points(stdout, *real_pts_ptr, *nb_real_roots_ptr); } fprintf(stdout, "]:\n"); } } if(dim > 0){ if (info_level > 0) { fprintf(stderr, "The ideal has positive dimension\n"); } if(files->out_file != NULL){ FILE *ofile2 = fopen(files->out_file, "a+"); //1 because dim is >0 fprintf(ofile2, "[1, %d, -1, []]:\n", gens->nvars); fclose(ofile2); } else{ fprintf(stdout, "[1, %d, -1, []]:\n", gens->nvars); } } } void manage_output(int b, int dim, int dquot, files_gb *files, data_gens_ff_t *gens, param_t *param, mpz_param_t *mpz_paramp, int get_param, long *nb_real_roots_ptr, interval **real_roots_ptr, real_point_t **real_pts_ptr, int info_level){ if(b == 0){ display_output(b, dim, dquot, files, gens, param, mpz_paramp, get_param, nb_real_roots_ptr, real_roots_ptr, real_pts_ptr, info_level); } if(b==-2){ fprintf(stderr, "Characteristic of the field here shouldn't be positive\n"); (*mpz_paramp)->dim = -2; } if(b==-3){ fprintf(stderr, "Problem when checking meta data\n"); (*mpz_paramp)->dim = -3; } } int core_msolve( int32_t la_option, int32_t use_signatures, int32_t nr_threads, int32_t info_level, int32_t initial_hts, int32_t max_pairs, int32_t elim_block_len, int32_t update_ht, int32_t generate_pbm, int32_t reduce_gb, int32_t print_gb, int32_t truncate_lifting, int32_t get_param, int32_t genericity_handling, int32_t saturate, int32_t colon, int32_t normal_form, int32_t normal_form_matrix, int32_t is_gb, int32_t precision, files_gb *files, data_gens_ff_t *gens, param_t **paramp, mpz_param_t *mpz_paramp, long *nb_real_roots_ptr, interval **real_roots_ptr, real_point_t **real_pts_ptr ) { param_t *param = NULL; int32_t *bld = NULL; int32_t **blen = NULL; int32_t **bexp = NULL; void **bcf = NULL; int b = 0; /* counter for randomly chosen linear forms */ int round = -1; restart: param = NULL; bld = malloc(sizeof(int32_t)); blen = malloc(sizeof(int32_t *)); bexp = malloc(sizeof(int32_t *)); bcf = malloc(sizeof(void *)); b = 0; if(gens->field_char > 0){ if (use_signatures > 0) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* data structures for basis, hash table and statistics */ bs_t *bs = NULL; ht_t *bht = NULL; md_t *st = NULL; /* for (int ii = 0; iinvars; ++ii) { * mul[ii] = 1; * } */ int success = 0; success = initialize_gba_input_data(&bs, &bht, &st, gens->lens, gens->exps, (void *)gens->cfs, 1073741827, 0 /* DRL order */, elim_block_len, gens->nvars, /* gens->field_char, 0 [> DRL order <], gens->nvars, */ gens->ngens, saturate, initial_hts, nr_threads, max_pairs, update_ht, la_option, use_signatures, 1 /* reduce_gb */, 0, info_level); if (st->homogeneous != 1) { fprintf(stderr, "Input system must be homogeneous.\n"); exit(1); } st->gfc = gens->field_char; if(info_level){ fprintf(stderr, "NOTE: Field characteristic is now corrected to %u\n", st->gfc); } if (!success) { printf("Bad input data, stopped computation.\n"); exit(1); } /* compute a gb for initial generators */ success = core_sba_schreyer(&bs, &bht, &st); if (!success) { printf("Problem with sba, stopped computation.\n"); exit(1); } int64_t nb = export_results_from_gba(bld, blen, bexp, bcf, &malloc, &bs, &bht, &st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->f4_ctime = ct1 - ct0; st->f4_rtime = rt1 - rt0; get_and_print_final_statistics(stderr, st, bs); if(nb==0){ fprintf(stderr, "Something went wrong during the computation\n"); return -1; } return 0; } if (saturate == 1) { /* positive characteristic */ /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* data structures for basis, hash table and statistics */ bs_t *bs = NULL; bs_t *sat = NULL; ht_t *bht = NULL; md_t *st = NULL; /* for (int ii = 0; iinvars; ++ii) { * mul[ii] = 1; * } */ int32_t error = 0; int success = 0; /* initialize generators of ideal, note the "gens->ngens-normal_form" which * means that we only take the first nr_gens-normal_form generators from * the input file, the last normal_form polynomial in the file will * be reduced w.r.t. the basis * * NOTE: There is a little hack here, instead of gens->field_char we * give 1073741827 as parameter, which ensures that all F4 internal * routines are the 32-bit implementations (since nf is at the moment * only implemented for 32-bit elements). Later on we set st-fc by hand * to the correct field characteristic. */ success = initialize_gba_input_data(&bs, &bht, &st, gens->lens, gens->exps, (void *)gens->cfs, 1073741827, 0 /* DRL order */, elim_block_len, gens->nvars, /* gens->field_char, 0 [> DRL order <], gens->nvars, */ gens->ngens, saturate, initial_hts, nr_threads, max_pairs, update_ht, la_option, use_signatures, 1 /* reduce_gb */, 0, info_level); st->gfc = gens->field_char; set_ff_bits(st, st->gfc); if(info_level){ fprintf(stderr, "NOTE: Field characteristic is now corrected to %u\n", st->gfc); } if(st->ff_bits < 32){ fprintf(stderr, "Error: not implemented yet (prime field of too low characteristic)\n"); return 1; } if (!success) { printf("Bad input data, stopped computation.\n"); exit(1); } if (is_gb == 1) { for (len_t k = 0; k < bs->ld; ++k) { bs->lmps[k] = k; bs->lm[k] = bht->hd[bs->hm[k][OFFSET]].sdm; bs->lml = bs->ld; } } else { sat = initialize_basis(st); sat->ht = bht; import_input_data(sat, st, gens->ngens-saturate, gens->ngens, gens->lens, gens->exps, (void *)gens->cfs, NULL); sat->ld = sat->lml = saturate; /* normalize_initial_basis(tbr, st->gfc); */ for (int k = 0; k < saturate; ++k) { sat->lmps[k] = k; /* fix input element in tbr */ } /* compute a gb for initial generators */ success = core_f4sat(bs, sat, st, &error); if (!success) { printf("Problem with f4sat, stopped computation.\n"); exit(1); } int64_t nb = export_results_from_gba(bld, blen, bexp, bcf, &malloc, &bs, &bht, &st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->f4_ctime = ct1 - ct0; st->f4_rtime = rt1 - rt0; get_and_print_final_statistics(stderr, st, bs); if(nb==0){ fprintf(stderr, "Something went wrong during the computation\n"); return -1; } if (print_gb) { print_ff_basis_data(files->out_file, "a", bs, bht, st, gens, print_gb); } } return 0; } if (colon == 1) { /* colon is 1 */ /* data structures for basis, hash table and statistics */ bs_t *bs = NULL; bs_t *tbr = NULL; ht_t *bht = NULL; md_t *st = NULL; double ct0, rt0, ct0p, rt0p, ct1, rt1, ct2, rt2, ct3, rt3, ct4, rt4; ct0 = cputime(); rt0 = realtime(); /* generate array for storing multiplier for polynomial * to be reduced by basis */ exp_t *mul = (exp_t *)calloc(gens->nvars, sizeof(exp_t)); /* for (int ii = 0; iinvars; ++ii) { * mul[ii] = 1; * } */ int32_t err = 0; /* initialize generators of ideal, note the "gens->ngens-1_form" which * means that we only take the first nr_gens-1 generators from * the input file, the last polynomial in the file will * be reduced w.r.t. the basis * * NOTE: There is a little hack here, instead of gens->field_char we * give 1073741827 as parameter, which ensures that all F4 internal * routines are the 32-bit implementations (since nf is at the moment * only implemented for 32-bit elements). Later on we set st-fc by hand * to the correct field characteristic. */ int success = initialize_gba_input_data(&bs, &bht, &st, gens->lens, gens->exps, (void *)gens->cfs, 1073741827, 0 /* DRL order */, elim_block_len, gens->nvars, /* gens->field_char, 0 [> DRL order <], gens->nvars, */ gens->ngens, 1, initial_hts, nr_threads, max_pairs, update_ht, la_option, use_signatures, 1 /* reduce_gb */, 0, info_level); st->gfc = gens->field_char; if(info_level){ fprintf(stderr, "NOTE: Field characteristic is now corrected to %u\n", st->gfc); } if (!success) { printf("Bad input data, stopped computation.\n"); exit(1); } ct0p = cputime(); rt0p = realtime(); if (info_level) { fprintf(stderr, "-------------------------------------------------\ ----------------------------------------\n"); fprintf(stderr, "INIT TIMING %13.2f sec (REAL) / %5.2f sec (CPU)\n", rt0p-rt0, ct0p-ct0); fprintf(stderr, "-------------------------------------------------\ ----------------------------------------\n"); } if (is_gb == 1) { for (len_t k = 0; k < bs->ld; ++k) { bs->lmps[k] = k; bs->lm[k] = bht->hd[bs->hm[k][OFFSET]].sdm; bs->lml = bs->ld; } } else { /* compute a gb for initial generators */ bs = core_gba(bs, st, &err, gens->field_char); if (err) { printf("Problem with F4, stopped computation.\n"); exit(1); } } export_results_from_gba(bld, blen, bexp, bcf, &malloc, &bs, &bht, &st); printf("size of basis: %u\n", bs->lml); ct1 = cputime(); rt1 = realtime(); if (info_level) { fprintf(stderr, "-------------------------------------------------\ ----------------------------------------\n"); fprintf(stderr, "F4 TIMING %13.2f sec (REAL) / %5.2f sec (CPU)\n", rt1-rt0p, ct1-ct0p); fprintf(stderr, "-------------------------------------------------\ ----------------------------------------\n"); } /* initialize data for elements to be reduced, * NOTE: Don't initialize BEFORE running core_f4, bht may * change, so hash values of tbr may become wrong. */ tbr = initialize_basis(st); tbr->ht = bht; import_input_data(tbr, st, gens->ngens-1, gens->ngens, gens->lens, gens->exps, (void *)gens->cfs, NULL); tbr->ld = tbr->lml = 1; /* normalize_initial_basis(tbr, st->gfc); */ for (int k = 0; k < 1; ++k) { tbr->lmps[k] = k; /* fix input element in tbr */ } /* compute normal form of last element in tbr */ tbr = core_nf(tbr, st, mul, bs, &err); if (err) { printf("Problem with normalform, stopped computation.\n"); exit(1); } /* print reduced element in tbr, last one is the input element */ /* printf ("normal form:\n"); */ /* print_msolve_polynomials_ff(stdout, 1, tbr->lml, tbr, bht, */ /* st, gens->vnames, 0); */ ct2 = cputime(); rt2 = realtime(); if (info_level) { fprintf(stderr, "-------------------------------------------------\ ----------------------------------------\n"); fprintf(stderr, "NF TIMING %13.2f sec (REAL) / %5.2f sec (CPU)\n", rt2-rt1, ct2-ct1); fprintf(stderr, "-------------------------------------------------\ ----------------------------------------\n"); } /* print all reduced elements in tbr, first one * is the input element */ /* print_msolve_polynomials_ff(stdout, 1, tbr->lml, tbr, bht, */ /* st, gens->vnames, 0); */ /* printf("\n"); */ /* list of monomials */ /* size of the list */ long suppsize= tbr->hm[tbr->lmps[1]][LENGTH]; // bs->hm[bs->lmps[1]][LENGTH] printf("Length of the support of phi: %lu\n", suppsize); /* sht and hcm will store the support of the normal form in tbr. */ ht_t *sht = initialize_secondary_hash_table(bht, st); hi_t *hcm = (hi_t *)malloc(sizeof(hi_t)); mat_t *mat = (mat_t *)calloc(1, sizeof(mat_t)); /* printf("Starts computation of normal form matrix\n"); */ get_normal_form_matrix(tbr, bht, 1, st, &sht, &hcm, &mat); printf("Length of union of support of all normal forms: %u\n", mat->nc); /* printf("\nUnion of support, sorted by decreasing monomial order:\n"); */ /* for (len_t k = 0; k < mat->nc; ++k) { */ /* for (len_t l = 1; l <= sht->nv; ++l) { */ /* printf("%2u ", sht->ev[hcm[k]][l]); */ /* } */ /* printf("\n"); */ /* } */ int32_t *bcf_ff = (int32_t *)(*bcf); int32_t *bexp_lm = get_lead_monomials(bld, blen, bexp, gens); long maxdeg = sht->ev[hcm[0]][0]; /* degree of the normal form */ for (long i = 0; i < bld[0]; i++) { long degi = 0; for (long k = 0; k < gens->nvars; k++) { degi += bexp_lm[i*gens->nvars+k]; } maxdeg = MAX(maxdeg,degi); } printf ("Maximal degree of the truncated staircase: %ld\n",maxdeg); long dquot; #define ZERO 0 #if ZERO int32_t *lmb= monomial_basis_colon (bld[0], gens->nvars, bexp_lm, &dquot, maxdeg); #else int32_t *lmb= monomial_basis_colon_no_zero (bld[0], gens->nvars, bexp_lm, &dquot, maxdeg); #endif /* printf("\nMonomial basis:\n"); */ /* for (len_t k = 0; k < dquot; ++k) { */ /* for (len_t l = 0; l < gens->nvars; ++l){ */ /* printf("%2u ", lmb[k*gens->nvars+l]); */ /* } */ /* printf("\n"); */ /* } */ printf("Subspace of quotient algebra has dimension: %ld\n",dquot); uint32_t * leftvector = calloc(dquot,sizeof (uint32_t)); uint32_t ** leftvectorsparam = malloc(2*(gens->nvars-1)*sizeof (uint32_t *)); for (long i = 0; i < 2*(gens->nvars-1); i++) { leftvectorsparam[i] = calloc(dquot,sizeof (uint32_t)); } /* we assume that the support of phi is enough to encode * the multiplication matrix */ /* we need the nf of sigma x_n for all sigma is this support */ #if ZERO sp_matfglmcol_t *matrix = build_matrixn_colon(lmb, dquot, bld[0], blen, bexp, bcf_ff, bexp_lm, tbr, bht, st, mul, bs, gens->nvars, gens->field_char, maxdeg, gens, leftvector, leftvectorsparam, suppsize); #else sp_matfglmcol_t *matrix = build_matrixn_colon_no_zero(lmb, dquot, bld[0], blen, bexp, bcf_ff, bexp_lm, tbr, bht, st, mul, bs, gens->nvars, gens->field_char, maxdeg, gens, leftvector, leftvectorsparam, suppsize); #endif #undef ZERO ct3 = cputime(); rt3 = realtime(); if (info_level) { fprintf(stderr, "-------------------------------------------------\ ----------------------------------------\n"); fprintf(stderr, "MATRIX TIMING %13.2f sec (REAL) / %5.2f sec (CPU)\n", rt3-rt2, ct3-ct2); fprintf(stderr, "-------------------------------------------------\ ----------------------------------------\n"); } nvars_t *linvars = calloc(gens->nvars, sizeof(nvars_t)); uint32_t *lineqs = calloc(gens->nvars,sizeof(uint32_t)); nvars_t *squvars = calloc(gens->nvars-1, sizeof(nvars_t)); param_t * param = nmod_fglm_guess_colon(matrix, gens->field_char, leftvector, leftvectorsparam, gens->nvars, 0, linvars, lineqs, squvars, 1, st); ct4 = cputime(); rt4 = realtime(); if (info_level) { fprintf(stderr, "-------------------------------------------------\ ----------------------------------------\n"); fprintf(stderr, "FGLM TIMING %13.2f sec (REAL) / %5.2f sec (CPU)\n", rt4-rt3, ct4-ct3); fprintf(stderr, "-------------------------------------------------\ ----------------------------------------\n"); } display_fglm_param(stdout, param); if (info_level) { fprintf(stderr, "-------------------------------------------------\ ----------------------------------------\n"); fprintf(stderr, "TOTAL TIMING %13.2f sec (REAL) / %5.2f sec (CPU)\n", rt4-rt0, ct4-ct0); fprintf(stderr, "-------------------------------------------------\ ----------------------------------------\n"); fprintf(stderr, "INIT PERCTG %13.2f%% (REAL) / %5.2f%% (CPU)\n", 100*(rt0p-rt0)/(rt4-rt0), 100*(ct0p-ct0)/(ct4-ct0)); fprintf(stderr, "F4 PERCTG %13.2f%% (REAL) / %5.2f%% (CPU)\n", 100*(rt1-rt0p)/(rt4-rt0), 100*(ct1-ct0p)/(ct4-ct0)); fprintf(stderr, "NF PERCTG %13.2f%% (REAL) / %5.2f%% (CPU)\n", 100*(rt2-rt1)/(rt4-rt0), 100*(ct2-ct1)/(ct4-ct0)); fprintf(stderr, "MATRIX PERCTG %13.2f%% (REAL) / %5.2f%% (CPU)\n", 100*(rt3-rt2)/(rt4-rt0), 100*(ct3-ct2)/(ct4-ct0)); fprintf(stderr, "FGLM PERCTG %13.2f%% (REAL) / %5.2f%% (CPU)\n", 100*(rt4-rt3)/(rt4-rt0), 100*(ct4-ct3)/(ct4-ct0)); fprintf(stderr, "-------------------------------------------------\ ----------------------------------------\n"); } free(param); free(squvars); free(lineqs); free(linvars); free(matrix); for (long i = 0; i < 2*(gens->nvars-1); i++) { free(leftvectorsparam[i]); } free(leftvectorsparam); free(leftvector); free(lmb); free(bexp_lm); free(bcf_ff); free(hcm); free (mul); hcm = NULL; if (sht != NULL) { free_hash_table(&sht); } /* free and clean up */ if (bs != NULL) { free_basis(&bs); } if (tbr != NULL) { free_basis(&tbr); } free(st); st = NULL; free_shared_hash_data(bht); if (bht != NULL) { free_hash_table(&bht); } return 0; } /* no saturate = 0 */ /* no colon = 0 */ if (normal_form == 0) {/* positive characteristic */ int dim = - 2; long dquot = -1; if(elim_block_len > 0 && print_gb == 0){ if(info_level){ fprintf(stderr, "Warning: elim order not available for rational parametrizations\n"); fprintf(stderr, "Computing Groebner basis\n"); print_gb=2; } } b = real_msolve_qq(mpz_paramp, ¶m, &dim, &dquot, nb_real_roots_ptr, real_roots_ptr, real_pts_ptr, gens, initial_hts, nr_threads, max_pairs, elim_block_len, update_ht, la_option, use_signatures, info_level, print_gb, generate_pbm, precision, files, round, get_param); if(print_gb){ return 0; } manage_output(b, dim, dquot, files, gens, param, mpz_paramp, get_param, nb_real_roots_ptr, real_roots_ptr, real_pts_ptr, info_level); /* if (b == 0 && gens->field_char > 0) { */ /* if(dim == 0){ */ /* if(files->out_file != NULL){ */ /* FILE *ofile = fopen(files->out_file, "a"); */ /* if(dquot == 0){ */ /* fprintf(ofile, "[-1]:\n"); */ /* return 0; */ /* } */ /* display_fglm_param_maple(ofile, param); */ /* fclose(ofile); */ /* } */ /* else{ */ /* if(dquot == 0){ */ /* fprintf(stdout, "[-1]:\n"); */ /* return 0; */ /* } */ /* display_fglm_param_maple(stdout, param); */ /* } */ /* return 0; */ /* } */ /* } */ if (b == 1) { free(bld); bld = NULL; free(blen); blen = NULL; free(bexp); bexp = NULL; free(bcf); bcf = NULL; free(param); param = NULL; if (genericity_handling > 0) { if (change_variable_order_in_input_system(gens, info_level)) { goto restart; } if (genericity_handling == 2) { if (add_linear_form_to_input_system(gens, info_level)) { goto restart; } } } fprintf(stderr, "\n=====> Computation failed <=====\n"); fprintf(stderr, "Try to add a random linear form with "); fprintf(stderr, "a new variable\n"); fprintf(stderr, "(smallest w.r.t. DRL) to the input system. "); fprintf(stderr, "This will\n"); fprintf(stderr, "be done automatically if you run msolve with option\n"); fprintf(stderr, "\"-c2\" which is the default.\n"); } if(b == 2){ free(bld); bld = NULL; free(blen); blen = NULL; free(bexp); bexp = NULL; free(bcf); bcf = NULL; free(param); param = NULL; round++; if(gens->change_var_order >= 0){ undo_variable_order_change(gens); } if (genericity_handling == 2) { if (add_random_linear_form_to_input_system(gens, info_level)) { goto restart; } } fprintf(stderr, "\n=====> Computation failed <=====\n"); fprintf(stderr, "Try to add a random linear form with "); fprintf(stderr, "a new variable\n"); fprintf(stderr, "(smallest w.r.t. DRL) to the input system. "); fprintf(stderr, "This will\n"); fprintf(stderr, "be done automatically if you run msolve with option\n"); fprintf(stderr, "\"-c2\" which is the default.\n"); } } else { /* normal_form is 1 */ /* data structures for basis, hash table and statistics */ bs_t *bs = NULL; bs_t *tbr = NULL; ht_t *bht = NULL; md_t *st = NULL; /* for (int ii = 0; iinvars; ++ii) { * mul[ii] = 1; * } */ int32_t err = 0; int success = 0; /* initialize generators of ideal, note the "gens->ngens-normal_form" which * means that we only take the first nr_gens-normal_form generators from * the input file, the last normal_form polynomial in the file will * be reduced w.r.t. the basis * * NOTE: There is a little hack here, instead of gens->field_char we * give 1073741827 as parameter, which ensures that all F4 internal * routines are the 32-bit implementations (since nf is at the moment * only implemented for 32-bit elements). Later on we set st-fc by hand * to the correct field characteristic. */ success = initialize_gba_input_data(&bs, &bht, &st, gens->lens, gens->exps, (void *)gens->cfs, gens->field_char, 0 /* DRL order */, elim_block_len, gens->nvars, /* gens->field_char, 0 [> DRL order <], gens->nvars, */ gens->ngens, normal_form, initial_hts, nr_threads, max_pairs, update_ht, la_option, use_signatures, 1 /* reduce_gb */, 0, info_level); st->gfc = gens->field_char; if (!success) { printf("Bad input data, stopped computation.\n"); exit(1); } if (is_gb == 1) { for (len_t k = 0; k < bs->ld; ++k) { bs->lmps[k] = k; bs->lm[k] = bht->hd[bs->hm[k][OFFSET]].sdm; bs->lml = bs->ld; } } else { /* compute a gb for initial generators */ bs = core_gba(bs, st, &err, gens->field_char); if (err) { printf("Problem with F4, stopped computation.\n"); exit(1); } } /* initialize data for elements to be reduced, * NOTE: Don't initialize BEFORE running core_f4, bht may * change, so hash values of tbr may become wrong. */ tbr = initialize_basis(st); tbr->ht = bht; import_input_data(tbr, st, gens->ngens-normal_form, gens->ngens, gens->lens, gens->exps, (void *)gens->cfs, NULL); tbr->ld = tbr->lml = normal_form; /* normalize_initial_basis(tbr, st->gfc); */ for (int k = 0; k < normal_form; ++k) { tbr->lmps[k] = k; /* fix input element in tbr */ } /* generate array for storing multiplier for polynomial * to be reduced by basis */ exp_t *mul = (exp_t *)calloc(bht->evl, sizeof(exp_t)); /* compute normal form of last element in tbr */ tbr = core_nf(tbr, st, mul, bs, &err); if (err) { printf("Problem with normalform, stopped computation.\n"); exit(1); } /* print all reduced elements in tbr, first normal_form ones * are the input elements */ print_ff_nf_data(files->out_file, "a", 0, normal_form, tbr, bht, st, gens, 2); if (normal_form_matrix > 0) { /* sht and hcm will store the union of the support * of all normal forms in tbr. */ ht_t *sht = initialize_secondary_hash_table(bht, st); hi_t *hcm = (hi_t *)malloc(sizeof(hi_t)); mat_t *mat = (mat_t *)calloc(1, sizeof(mat_t)); printf("\nStarts computation of normal form matrix\n"); get_normal_form_matrix(tbr, tbr->ht, normal_form, st, &sht, &hcm, &mat); printf("\n\nLength of union of support of all normal forms: %u\n", mat->nc); printf("\nUnion of support, sorted by decreasing monomial order:\n"); for (len_t k = 0; k < mat->nc; ++k) { for (len_t l = 1; l <= sht->nv; ++l) { printf("%2u ", sht->ev[hcm[k]][l]); } printf("\n"); } /* sparse represented matrix of normal forms, note that the column entries * of the rows are not sorted, but you can do so using any sort algorithm */ printf("\nMatrix of normal forms (sparse format, note that entries are\n"); printf("NOT completely sorted by column index):\n"); int64_t nterms = 0; for (len_t k = 0; k < mat->nr; ++k) { printf("row %u | ", k); for (len_t l = 0; l < mat->tr[k][LENGTH]; ++l) { printf("%u at %u, ", tbr->cf_32[mat->tr[k][COEFFS]][l], mat->tr[k][l+OFFSET]); } printf("\n"); nterms += mat->tr[k][LENGTH]; } nterms *= 100; /* for percentage */ double density = (double)nterms / (double)mat->nr / (double)mat->nc; printf("\nMatrix of normal forms (dense format)\n"); cf32_t *dr = (cf32_t *)malloc( (unsigned long)mat->nc * sizeof(cf32_t)); for (len_t k = 0; k < mat->nr; ++k) { memset(dr, 0, (unsigned long)mat->nc * sizeof(cf32_t)); printf("row %u | ", k); for (len_t l = 0; l < mat->tr[k][LENGTH]; ++l) { dr[mat->tr[k][l+OFFSET]] = tbr->cf_32[mat->tr[k][COEFFS]][l]; } for (len_t l = 0; l < mat->nc; ++l) { printf("%u, ", dr[l]); } printf("\n"); } printf("density of matrix: %.2f%%\n", density); for (len_t k = 0; k < mat->nr; ++k) { free(mat->tr[k]); } free(mat); mat = NULL; free(hcm); hcm = NULL; if (sht != NULL) { free_hash_table(&sht); } } /* free and clean up */ if (bs != NULL) { free_basis_without_hash_table(&bs); } if (tbr != NULL) { free_basis(&tbr); } free(st); st = NULL; } return 0; } else{/* characteristic is 0 */ #if 0 if (elim_block_len > 0) { /* characteristic is 0 */ /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); uint32_t field_char = gens->field_char; const uint32_t prime_start = pow(2, 30); const int32_t nr_primes = nr_threads; /* initialize stuff */ md_t *st = allocate_meta_data(); int *invalid_gens = NULL; int32_t monomial_order = 0; int32_t reduce_gb = 1; int res = validate_input_data(&invalid_gens, gens->mpz_cfs, gens->lens, &field_char, &monomial_order, &elim_block_len, &gens->nvars, &gens->ngens, &saturate, &initial_hts, &nr_threads, &max_pairs, &update_ht, &la_option, &use_signatures, &reduce_gb, &info_level); /* all data is corrupt */ if (res == -1) { fprintf(stderr, "Invalid input generators, msolve now terminates.\n"); free(invalid_gens); return -3; } /* checks and set all meta data. if a nonzero value is returned then * some of the input data is corrupted. */ if (check_and_set_meta_data_trace(st, gens->lens, gens->exps, (void *)gens->mpz_cfs, invalid_gens, gens->field_char, 0, elim_block_len, gens->nvars, gens->ngens, saturate, initial_hts, nr_threads, max_pairs, update_ht, la_option, use_signatures, 1, prime_start, nr_primes, 0, info_level)) { free(st); return -3; } /* lucky primes */ primes_t *lp = (primes_t *)calloc(1, sizeof(primes_t)); /******************* * initialize basis *******************/ bs_t *bs_qq = initialize_basis(st); /* initialize basis hash table, update hash table, symbolic hash table */ ht_t *bht = initialize_basis_hash_table(st); /* hash table to store the hashes of the multiples of * the basis elements stored in the trace */ ht_t *tht = initialize_secondary_hash_table(bht, st); /* read in ideal, move coefficients to integers */ import_input_data(bs_qq, st, 0, st->ngens_input, gens->lens, gens->exps, (void *)gens->mpz_cfs, invalid_gens); print_initial_statistics(stderr, st); /* for faster divisibility checks, needs to be done after we have * read some input data for applying heuristics */ calculate_divmask(bht); /* sort initial elements, smallest lead term first */ sort_r(bs_qq->hm, (unsigned long)bs_qq->ld, sizeof(hm_t *), initial_input_cmp, bht); remove_content_of_initial_basis(bs_qq); /* generate lucky prime numbers */ generate_lucky_primes(lp, bs_qq, st->prime_start, st->nprimes); /* generate array to store modular bases */ bs_t **bs = (bs_t **)calloc((unsigned long)st->nprimes, sizeof(bs_t *)); /* initialize tracer */ trace_t *trace = initialize_trace(bs_qq, st); srand(time(0)); uint32_t prime = next_prime(1<<30); prime = next_prime(rand() % (1303905301 - (1<<30) + 1) + (1<<30)); while(is_lucky_prime_ui(prime, bs_qq)){ prime = next_prime(rand() % (1303905301 - (1<<30) + 1) + (1<<30)); } uint32_t primeinit = prime; lp->p[0] = primeinit; if (is_gb == 1) { for (len_t k = 0; k < bs_qq->ld; ++k) { bs_qq->lmps[k] = k; bs_qq->lm[k] = bht->hd[bs_qq->hm[k][OFFSET]].sdm; bs_qq->lml = bs_qq->ld; } } st->laopt = 44; bs_t *bsprob = modular_f4(bs_qq, bht, st, lp->p[0]); st->laopt = 2; /* compute a gb for initial generators */ gba_trace_learning_phase( trace, tht, bs_qq, bht, st, lp->p[0]); /* int64_t nb = export_results_from_gba(bld, blen, bexp, * bcf, &bs, &bht, &st); */ /* timings */ ct1 = cputime(); rt1 = realtime(); st->f4_ctime = ct1 - ct0; st->f4_rtime = rt1 - rt0; if (st->info_level > 1) { print_final_statistics(stderr, st); } if(info_level){ fprintf(stderr, "\nStarts trace based multi-modular computations\n"); } int i; ht_t *lht = copy_hash_table(bht); prime = next_prime(1<<30); /* while(rerun == 1 || mcheck == 1){ */ /* generate lucky prime numbers */ prime = next_prime(prime); lp->p[0] = prime; while(is_lucky_prime_ui(prime, bs_qq) || prime==primeinit){ prime = next_prime(prime); lp->p[0] = prime; } for(len_t i = 1; i < st->nprimes; i++){ prime = next_prime(prime); lp->p[i] = prime; while(is_lucky_prime_ui(prime, bs_qq) || prime==primeinit){ prime = next_prime(prime); lp->p[i] = prime; } } prime = lp->p[st->nprimes - 1]; double ca0; double stf4 = 0; for (i = 0; i < st->nprimes; ++i){ ca0 = realtime(); bs[i] = gba_trace_application_phase( trace, tht, bs_qq, lht, st, lp->p[i]); stf4 = realtime()-ca0; printf("F4 trace timing %13.2f\n", stf4); /* printf("bs[%u]->lml = %u\n", i, bs[i]->lml); */ } /* } */ return 0; } #endif /* characteristic is 0 */ /* characteristic is 0 and elim_block = 0 */ if (saturate == 1) { /* characteristic is 0 and elim_block = 0 */ /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); uint32_t field_char = gens->field_char; const uint32_t prime_start = pow(2, 30); const int32_t nr_primes = nr_threads; /* data structures for basis, hash table and statistics */ bs_t *sat_qq = NULL; /* initialize stuff */ md_t *st = allocate_meta_data(); int *invalid_gens = NULL; int32_t monomial_order = 0; int32_t reduce_gb = 1; int res = validate_input_data(&invalid_gens, gens->mpz_cfs, gens->lens, &field_char, &monomial_order, &elim_block_len, &gens->nvars, &gens->ngens, &saturate, &initial_hts, &nr_threads, &max_pairs, &update_ht, &la_option, &use_signatures, &reduce_gb, &info_level); /* all data is corrupt */ if (res == -1) { fprintf(stderr, "Invalid input generators, msolve now terminates.\n"); free(invalid_gens); return -3; } /* checks and set all meta data. if a nonzero value is returned then * some of the input data is corrupted. */ if (check_and_set_meta_data_trace(st, gens->lens, gens->exps, (void *)gens->mpz_cfs, invalid_gens, field_char, 0, elim_block_len, gens->nvars, gens->ngens, saturate, initial_hts, nr_threads, max_pairs, update_ht, la_option, use_signatures, 1, prime_start, nr_primes, 0, info_level)) { free(st); return -3; } /* lucky primes */ primes_t *lp = (primes_t *)calloc(1, sizeof(primes_t)); /******************* * initialize basis *******************/ bs_t *bs_qq = initialize_basis(st); /* initialize basis hash table, update hash table, symbolic hash table */ ht_t *bht = bs_qq->ht; /* hash table to store the hashes of the multiples of * the basis elements stored in the trace */ ht_t *tht = initialize_secondary_hash_table(bht, st); /* read in ideal, move coefficients to integers */ import_input_data(bs_qq, st, 0, st->ngens_input, gens->lens, gens->exps, (void *)gens->mpz_cfs, invalid_gens); free(invalid_gens); invalid_gens = NULL; print_initial_statistics(stderr, st); /* for faster divisibility checks, needs to be done after we have * read some input data for applying heuristics */ calculate_divmask(bht); /* sort initial elements, smallest lead term first */ sort_r(bs_qq->hm, (unsigned long)bs_qq->ld, sizeof(hm_t *), initial_input_cmp, bht); remove_content_of_initial_basis(bs_qq); /* generate lucky prime numbers */ generate_lucky_primes(lp, bs_qq, st->prime_start, st->nprimes); /* generate array to store modular bases */ bs_t **bs = (bs_t **)calloc((unsigned long)st->nprimes, sizeof(bs_t *)); /* initialize tracer */ trace_t *trace = initialize_trace(bs_qq, st); st->tr = trace; srand(time(0)); uint32_t prime = next_prime(1<<30); prime = next_prime(rand() % (1303905301 - (1<<30) + 1) + (1<<30)); while(is_lucky_prime_ui(prime, bs_qq)){ prime = next_prime(rand() % (1303905301 - (1<<30) + 1) + (1<<30)); } uint32_t primeinit = prime; lp->p[0] = primeinit; if (is_gb == 1) { for (len_t k = 0; k < bs_qq->ld; ++k) { bs_qq->lmps[k] = k; bs_qq->lm[k] = bht->hd[bs_qq->hm[k][OFFSET]].sdm; bs_qq->lml = bs_qq->ld; } } sat_qq = initialize_basis(st); sat_qq->ht = bht; import_input_data( sat_qq, st, gens->ngens-saturate, gens->ngens, gens->lens, gens->exps, (void *)gens->mpz_cfs, NULL); sat_qq->ld = sat_qq->lml = saturate; /* normalize_initial_basis(tbr, st->gfc); */ for (int k = 0; k < saturate; ++k) { sat_qq->lmps[k] = k; /* fix input element in tbr */ } printf("LEARNING PHASE -- PART 1\n"); f4sat_trace_learning_phase_1( trace, tht, bs_qq, sat_qq, &bht, st, lp->p[0]); /* int64_t nb = export_results_from_gba(bld, blen, bexp, * bcf, &bs, &bht, &st); */ /* timings */ ct1 = cputime(); rt1 = realtime(); st->f4_ctime = ct1 - ct0; st->f4_rtime = rt1 - rt0; get_and_print_final_statistics(stderr, st, bs_qq); if(info_level){ fprintf(stderr, "\nStarts trace based multi-modular computations\n"); } prime = next_prime(1<<30); lp->p[0] = prime; printf("LEARNING PHASE -- PART 2\n"); f4sat_trace_learning_phase_2( trace, tht, bs_qq, sat_qq, &bht, st, lp->p[0]); /* int64_t nb = export_results_from_gba(bld, blen, bexp, * bcf, &bs, &bht, &st); */ /* timings */ ct1 = cputime(); rt1 = realtime(); st->f4_ctime = ct1 - ct0; st->f4_rtime = rt1 - rt0; get_and_print_final_statistics(stderr, st, bs_qq); if(info_level){ fprintf(stderr, "\nStarts trace based multi-modular computations\n"); } int i; ht_t *lht = copy_hash_table(bht); prime = next_prime(1<<30); /* while(rerun == 1 || mcheck == 1){ */ /* generate lucky prime numbers */ prime = next_prime(prime); lp->p[0] = prime; while(is_lucky_prime_ui(prime, bs_qq) || prime==primeinit){ prime = next_prime(prime); lp->p[0] = prime; } for(len_t i = 1; i < st->nprimes; i++){ prime = next_prime(prime); lp->p[i] = prime; while(is_lucky_prime_ui(prime, bs_qq) || prime==primeinit){ prime = next_prime(prime); lp->p[i] = prime; } } prime = lp->p[st->nprimes - 1]; double ca0; double stf4 = 0; for (i = 0; i < st->nprimes; ++i){ ca0 = realtime(); bs[i] = f4sat_trace_application_phase( trace, tht, bs_qq, sat_qq, lht, st, lp->p[i]); stf4 = realtime()-ca0; printf("F4 trace timing %13.2f\n", stf4); /* printf("bs[%u]->lml = %u\n", i, bs[i]->lml); */ } /* } */ return 0; } else { /* characteristic is 0 and elim_block = 0 and saturate = 0 */ int dim = - 2; long dquot = -1; if(elim_block_len && print_gb == 0){ if(info_level){ fprintf(stderr, "Warning: elim order not available for rational parametrizations\n"); fprintf(stderr, "Computing Groebner basis\n"); print_gb=2; } } if(print_gb){ msflags_t flags; flags->ht_size = initial_hts; flags->nr_threads = nr_threads; flags->max_nr_pairs = max_pairs; flags->elim_block_len = elim_block_len; flags->truncate_lifting = truncate_lifting; flags->reset_ht = update_ht; flags->la_option = la_option; flags->use_signatures = use_signatures; flags->info_level = info_level; flags->pbm_file = generate_pbm; flags->print_gb = print_gb; flags->files = files; print_msolve_gbtrace_qq(gens, flags); return 0; } b = real_msolve_qq(mpz_paramp, ¶m, &dim, &dquot, nb_real_roots_ptr, real_roots_ptr, real_pts_ptr, gens, initial_hts, nr_threads, max_pairs, elim_block_len, update_ht, la_option, use_signatures, info_level, print_gb, generate_pbm, precision, files, round, get_param); if(print_gb){ return 0; } manage_output(b, dim, dquot, files, gens, param, mpz_paramp, get_param, nb_real_roots_ptr, real_roots_ptr, real_pts_ptr, info_level); if (b == 1) { free(bld); bld = NULL; free(blen); blen = NULL; free(bexp); bexp = NULL; free(bcf); bcf = NULL; free(param); param = NULL; if (genericity_handling > 0) { if (change_variable_order_in_input_system(gens, info_level)) { goto restart; } if (genericity_handling == 2) { if (add_linear_form_to_input_system(gens, info_level)) { goto restart; } } } fprintf(stderr, "\n=====> Computation failed <=====\n"); fprintf(stderr, "Try to add a random linear form with "); fprintf(stderr, "a new variable\n"); fprintf(stderr, "(smallest w.r.t. DRL) to the input system. "); fprintf(stderr, "This will\n"); fprintf(stderr, "be done automatically if you run msolve with option\n"); fprintf(stderr, "\"-c2\" which is the default.\n"); (*mpz_paramp)->dim = -1; } if(b == -4){ fprintf(stderr, "Bad prime chosen initially\n"); goto restart; /* (*mpz_paramp)->dim = -4; */ } if(b == 2){ free(bld); bld = NULL; free(blen); blen = NULL; free(bexp); bexp = NULL; free(bcf); bcf = NULL; free(param); param = NULL; round++; if(gens->change_var_order >= 0){ undo_variable_order_change(gens); } if (genericity_handling == 2) { if (add_random_linear_form_to_input_system(gens, info_level)) { goto restart; } } fprintf(stderr, "\n=====> Computation failed <=====\n"); fprintf(stderr, "Try to add a random linear form with "); fprintf(stderr, "a new variable\n"); fprintf(stderr, "(smallest w.r.t. DRL) to the input system. "); fprintf(stderr, "This will\n"); fprintf(stderr, "be done automatically if you run msolve with option\n"); fprintf(stderr, "\"-c2\" which is the default.\n"); } } free(bld); free(blen); free(bexp); free(bcf); /* get parametrization */ *paramp = param; return !(b==0); } } static void export_julia_rational_parametrization_qq( void *(*mallocp) (size_t), int32_t *load, int32_t *nvars, int32_t *dim, int32_t *dim_quot, int32_t **lens, char ***var_namesp, void **cfs_linear_form, void **cfs, void **real_sols_num, int32_t **real_sols_den, data_gens_ff_t *gens, /* might change vnames, thus not const */ const mpz_param_t param, const long nb_real_roots, const real_point_t *real_pts ) { int32_t i, j; int64_t ctr = 0; *load = (int32_t)param->nvars+1; *dim = (int32_t)param->dim; *dim_quot = (int32_t)param->dquot; *nvars = (int32_t)gens->nvars; /* keep variable names for returning rational parametrization */ *var_namesp = gens->vnames; gens->vnames = NULL; mpz_t *cf_lf = NULL; /* check existence of linear form */ if (gens->linear_form_base_coef > 0) { cf_lf = (mpz_t *)(*mallocp)( (unsigned long)(gens->nvars) * sizeof(mpz_t)); int64_t len = 0; for (i = 0; i < gens->ngens-1; ++i) { len += 2*gens->lens[i]; /* numerator plus denominator, thus "2*" */ } j = 0; for (i = 0; i < 2*gens->nvars; i += 2) { mpz_init_set(cf_lf[j++], *(gens->mpz_cfs[i+len])); } } if ((param->dim > 0) || (param->dim == 0 && param->dquot == 0)) { *lens = NULL; *cfs = NULL; } else { int32_t *len = (int32_t *)(*mallocp)( (unsigned long)(param->nvars+1) * sizeof(int32_t)); /* precompute number of all terms of all polynomials */ int64_t nterms = 0; nterms += (int64_t)param->elim->length; len[0] = (int32_t)param->elim->length; nterms += (int64_t)param->denom->length; len[1] = (int32_t)param->denom->length; /* In the following we add one more term since each coords[i] polynomial * also gets another coefficient for the correct denominator in the * rational parametrization of the solution set. */ for (i = 0; i < param->nvars-1; ++i) { nterms += param->coords[i]->length+1; len[i+2] = param->coords[i]->length+1; } mpz_t *cf = (mpz_t *)(*mallocp)( (unsigned long)(nterms) * sizeof(mpz_t)); /* store elim */ for (i = 0; i < param->elim->length; ++i) { mpz_init_set((cf+ctr)[i], param->elim->coeffs[i]); } ctr += param->elim->length; /* store denom */ for (i = 0; i < param->denom->length; ++i) { mpz_init_set((cf+ctr)[i], param->denom->coeffs[i]); } ctr += param->denom->length; /* store param */ for (i = 0; i < param->nvars-1; ++i) { for (j = 0; j < param->coords[i]->length; ++j) { mpz_init_set((cf+ctr)[j], param->coords[i]->coeffs[j]); } mpz_init_set((cf+ctr)[j], param->cfs[i]); ctr += param->coords[i]->length+1; } *lens = len; *cfs = (void *)cf; *cfs_linear_form = (void *)cf_lf; /* if there are no real solutions return the parametrization at least */ if (nb_real_roots <= 0) { return; } const long nb_real_roots_intervall = 2 * nb_real_roots; mpz_t *sols_num = (mpz_t *)(*mallocp)( (unsigned long)nb_real_roots_intervall * real_pts[0]->nvars * sizeof(mpz_t)); int32_t *sols_den = (int32_t *)(*mallocp)( (unsigned long)nb_real_roots_intervall * real_pts[0]->nvars * sizeof(int32_t)); /* mpz_t tmp; * mpz_init(tmp); */ ctr = 0; for (i = 0; i < nb_real_roots; ++i) { for (j = 0; j < real_pts[i]->nvars; ++j) { /* mpz_add(tmp, real_pts[i]->coords[j]->val_do, * real_pts[i]->coords[j]->val_up); */ mpz_init_set(sols_num[ctr], real_pts[i]->coords[j]->val_do); sols_den[ctr++] = real_pts[i]->coords[j]->k_do; mpz_init_set(sols_num[ctr], real_pts[i]->coords[j]->val_up); sols_den[ctr++] = real_pts[i]->coords[j]->k_up; } } *real_sols_num = (void *)sols_num; *real_sols_den = sols_den; } } void msolve_julia( void *(*mallocp) (size_t), int32_t *rp_ld, int32_t *rp_nr_vars, int32_t *rp_dim, int32_t *rp_dquot, int32_t **rp_lens, char ***rp_var_namesp, void **rp_cfs_linear_form, void **rp_cfs, int32_t *n_real_sols, void **real_sols_num, int32_t **real_sols_den, int32_t *lens, int32_t *exps, void *cfs, char **var_names, char *output_file, const uint32_t field_char, const int32_t mon_order, const int32_t elim_block_len, const int32_t nr_vars, const int32_t nr_gens, const int32_t initial_hts, const int32_t nr_threads, const int32_t max_nr_pairs, const int32_t reset_ht, const int32_t la_option, const int32_t use_signatures, const int32_t print_gb, const int32_t get_param, const int32_t genericity_handling, const int32_t precision, const int32_t info_level ) { /* timinigs */ double st0 = cputime(); double rt0 = realtime(); len_t i; files_gb *files = calloc(1, sizeof(files_gb)); if (output_file != NULL) { files->out_file = output_file; } data_gens_ff_t *gens = allocate_data_gens(); unsigned long nterms = 0; for (i = 0; i < nr_gens; ++i) { nterms += lens[i]; } gens->nvars = nr_vars; gens->ngens = nr_gens; gens->field_char = field_char; gens->change_var_order = -1; gens->linear_form_base_coef = 0; /* gens->vnames = var_names; */ gens->vnames = (char **)malloc((unsigned long)nr_vars * sizeof(char *)); for (i = 0; i < nr_vars; ++i) { gens->vnames[i] = calloc((unsigned long)strlen(var_names[i]), sizeof(char)); memcpy(gens->vnames[i], var_names[i], (unsigned long)strlen(var_names[i]) * sizeof(char)); } /* gens->lens = lens; */ gens->lens = (int32_t *)malloc((unsigned long)nr_gens * sizeof(int32_t)); memcpy(gens->lens, lens, (unsigned long)nr_gens * sizeof(int32_t)); /* gens->exps = exps; */ gens->exps = (int32_t *)malloc(nterms * nr_vars * sizeof(int32_t)); memcpy(gens->exps, exps, nterms * nr_vars * sizeof(int32_t)); gens->rand_linear = 0; if (field_char > 0) { gens->cfs = (int32_t *)malloc(nterms * sizeof(int32_t)); memcpy(gens->cfs, (int32_t *)cfs, nterms * sizeof(int32_t)); /* gens->cfs = (int32_t *)cfs; */ } else { if (field_char == 0) { gens->mpz_cfs = (mpz_t **)malloc(nterms * 2 * sizeof(mpz_t *)); for (i = 0; i < 2*nterms; ++i) { gens->mpz_cfs[i] = (mpz_t *)malloc(sizeof(mpz_t)); mpz_init_set(*(gens->mpz_cfs[i]), *(((mpz_t **)cfs)[i])); } } } /* data structures for parametrization */ param_t *param = NULL; mpz_param_t mpz_param; mpz_param_init(mpz_param); long nb_real_roots = 0; interval *real_roots = NULL; real_point_t *real_pts = NULL; /* main msolve functionality */ int ret = core_msolve(la_option, use_signatures, nr_threads, info_level, initial_hts, max_nr_pairs, elim_block_len, reset_ht, 0 /* generate pbm */, 1 /* reduce_gb */, print_gb, 0 /*truncate_lifting*/, get_param, genericity_handling, 0 /* saturate */, 0 /* colon */, 0 /* normal_form */, 0 /* normal_form_matrix */, 0 /* is_gb */, precision, files, gens, ¶m, &mpz_param, &nb_real_roots, &real_roots, &real_pts); if (ret == -1) { exit(1); } *rp_dim = mpz_param->dim; char **rp_var_names = NULL; if (mpz_param->dim != -1) { export_julia_rational_parametrization_qq( mallocp, rp_ld, rp_nr_vars, rp_dim, rp_dquot, rp_lens, &rp_var_names, rp_cfs_linear_form, rp_cfs, real_sols_num, real_sols_den, gens, mpz_param, nb_real_roots, real_pts); } else { *rp_ld = -1; } /* clean up data storage, but do not free data handled by julia */ free(gens); gens = NULL; *rp_var_namesp = rp_var_names; /* free parametrization */ free(param); mpz_param_clear(mpz_param); *n_real_sols = nb_real_roots; free(real_roots); if (nb_real_roots > 0) { for(long i = 0; i < nb_real_roots; i++){ real_point_clear(real_pts[i]); } free(real_pts); } /* timings */ if (info_level > 0) { double st1 = cputime(); double rt1 = realtime(); fprintf(stderr, "-------------------------------------------------\ -----------------------------------\n"); fprintf(stderr, "msolve overall time %13.2f sec (elapsed) / %5.2f sec (cpu)\n", rt1-rt0, st1-st0); fprintf(stderr, "-------------------------------------------------\ -----------------------------------\n"); } } /* The parameters themselves are handled by julia, thus we only * free what they are pointing to, julia's garbage collector then * takes care of everything leftover. */ void free_msolve_julia_result_data( void (*freep) (void *), int32_t **res_len, void **res_cf, void **sols_num, int32_t **sols_den, const int64_t res_ld, const int64_t nr_sols, const int64_t field_char ) { int32_t *lens = *res_len; (*freep)(lens); lens = NULL; *res_len = lens; if (field_char > 0) { int32_t *numerators = *(int32_t **)sols_num; (*freep)(numerators); numerators = NULL; int32_t *cfs= *(int32_t **)res_cf; (*freep)(cfs); cfs = NULL; } else { /* denominators only exist if char == 0 */ int32_t *denominators = *sols_den; (*freep)(denominators); denominators = NULL; *sols_den = denominators; /* mpz_t **numerators = (mpz_t **)sols_num; * for (i = 0; i < nr_sols; ++i) { * (*freep)((*numerators)[i]); * } * (*freep)(*numerators); * *numerators = NULL; * mpz_t **cfs = (mpz_t **)res_cf; * for (i = 0; i < len; ++i) { * (*freep)((*cfs)[i]); * } * (*freep)(*cfs); * *cfs = NULL; */ } *sols_num = NULL; *res_cf = NULL; } msolve-0.6.5/src/msolve/msolve.h000066400000000000000000000117101456710632100166060ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef MSOLVE_MSOLVE_H #define MSOLVE_MSOLVE_H #include "msolve-data.h" int msolve_trace_qq( mpz_param_t *mpz_paramp, param_t **nmod_param, int *dim_ptr, long *dquot_ptr, data_gens_ff_t *gens, int32_t ht_size, int32_t nr_threads, int32_t max_nr_pairs, int32_t elim_block_len, int32_t reset_ht, int32_t la_option, int32_t use_signatures, int32_t info_level, int32_t print_gb, int32_t pbm_file, files_gb *files, int ); int msolve_probabilistic_qq( mpz_param_t mp_param, param_t **nmod_param, int *dim_ptr, long *dquot_ptr, data_gens_ff_t *gens, int32_t ht_size, int32_t nr_threads, int32_t max_nr_pairs, int32_t elim_block_len, int32_t reset_ht, int32_t la_option, int32_t use_signatures, int32_t info_level, int32_t print_gb, int32_t pbm_file, files_gb *files, int round ); #if 0 int msolve_qq( mpz_param_t mp_param, param_t **nmod_param, int *dim_ptr, long *dquot_ptr, data_gens_ff_t *gens, int32_t ht_size, int32_t nr_threads, int32_t max_nr_pairs, int32_t elim_block_len, int32_t reset_ht, int32_t la_option, int32_t info_level, int32_t print_gb, int32_t pbm_file, files_gb *files, int ); #endif int real_msolve_qq( mpz_param_t *mpz_paramp, param_t **nmod_param, int *dim_ptr, long *dquot_ptr, long *nb_real_roots_ptr, interval **real_roots_ptr, real_point_t **real_pts_ptr, data_gens_ff_t *gens, int32_t ht_size, int32_t nr_threads, int32_t max_nr_pairs, int32_t elim_block_len, int32_t reset_ht, int32_t la_option, int32_t use_signatures, int32_t info_level, int32_t print_gb, int32_t pbm_file, int32_t precision, files_gb *files, int, int32_t ); int core_msolve( int32_t la_option, int32_t use_signatures, int32_t nr_threads, int32_t info_level, int32_t initial_hts, int32_t max_pairs, int32_t elim_block_len, int32_t update_ht, int32_t generate_pbm, int32_t reduce_gb, int32_t print_gb, int32_t truncate_lifting, int32_t get_param, int32_t genericity_handling, int32_t saturate, int32_t colon, int32_t normal_form, int32_t normal_form_matrix, int32_t is_gb, int32_t precision, files_gb *files, data_gens_ff_t *gens, param_t **paramp, mpz_param_t *mpz_paramp, long *nb_real_roots_ptr, interval **real_roots_ptr, real_point_t **real_pts_ptr ); void msolve_julia( void *(*mallocp) (size_t), int32_t *rp_ld, int32_t *rp_nr_vars, int32_t *rp_dim, int32_t *rp_dquot, int32_t **rp_lens, char ***rp_var_namesp, void **rp_cfs_linear_form, void **rp_cfs, int32_t *n_real_sols, void **real_sols_num, int32_t **real_sols_den, int32_t *lens, int32_t *exps, void *cfs, char **var_names, char *output_file, const uint32_t field_char, const int32_t mon_order, const int32_t elim_block_len, const int32_t nr_vars, const int32_t nr_gens, const int32_t initial_hts, const int32_t nr_threads, const int32_t max_nr_pairs, const int32_t reset_ht, const int32_t la_option, const int32_t use_signatures, const int32_t print_gb, const int32_t get_param, const int32_t genericity_handling, const int32_t precision, const int32_t info_level ); void free_msolve_julia_result_data( void (*freep) (void *), int32_t **res_len, void **res_cf, void **sols_num, int32_t **sols_den, const int64_t res_ld, const int64_t nr_sols, const int64_t field_char ); #endif msolve-0.6.5/src/msolve/primes.c000066400000000000000000000022341456710632100165740ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ uint32_t primes_table[10] = {2, 3, 4, 5, 7, 11, 13, 17, 19, 23}; int is_prime(uint32_t n){ for(int i = 0; i < 10; i++){ if(n % primes_table[i] == 0){ return 0; } } for(uint32_t i = 5; i * i <= n; i += 6){ if((n % i)==0) return 0; if( (n % (i+2)) == 0) return 0; } return 1; } // assumes n >= 2 uint32_t next_prime(uint32_t n){ uint32_t cand = n + 1; while(!is_prime(cand)) cand++; return cand; } msolve-0.6.5/src/neogb/000077500000000000000000000000001456710632100147155ustar00rootroot00000000000000msolve-0.6.5/src/neogb/Makefile.am000066400000000000000000000017611456710632100167560ustar00rootroot00000000000000lib_LTLIBRARIES = libneogb.la libneogb_la_SOURCES = libneogb.h gb.c libneogb_ladir = $(includedir)/msolve/neogb libneogb_la_HEADERS =libneogb.h basis.h data.h engine.h f4.h sba.h hash.h \ io.h modular.h nf.h f4sat.h sort_r.h meta_data.h \ tools.h update.h libneogb_la_LDFLAGS = -release $(PACKAGE_VERSION) libneogb_la_CFLAGS = $(SIMD_FLAGS) $(CPUEXT_FLAGS) $(OPENMP_CFLAGS) EXTRA_DIST = basis.h \ data.h \ engine.h \ f4.h \ sba.h \ hash.h \ io.h \ modular.h \ nf.h \ f4sat.h \ sort_r.h \ meta_data.h \ tools.h \ update.h \ basis.c \ convert.c \ data.c \ engine.c \ f4.c \ f4sat.c \ sba.c \ hash.c \ io.c \ la_ff_16.c \ la_ff_32.c \ la_ff_8.c \ la_qq.c \ modular.c \ nf.c \ order.c \ meta_data.c \ symbol.c \ tools.c \ update.c msolve-0.6.5/src/neogb/basis.c000066400000000000000000000401621456710632100161650ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "basis.h" static void free_basis_elements( bs_t *bs ) { len_t i, j, len; if (bs->cf_8) { for (i = 0; i < bs->ld; ++i) { free(bs->cf_8[i]); bs->cf_8[i] = NULL; free(bs->hm[i]); bs->hm[i] = NULL; } } if (bs->cf_16) { for (i = 0; i < bs->ld; ++i) { free(bs->cf_16[i]); bs->cf_16[i] = NULL; free(bs->hm[i]); bs->hm[i] = NULL; } } if (bs->cf_32) { for (i = 0; i < bs->ld; ++i) { free(bs->cf_32[i]); bs->cf_32[i] = NULL; free(bs->hm[i]); bs->hm[i] = NULL; } } if (bs->cf_qq) { for (i = 0; i < bs->ld; ++i) { len = bs->hm[i][LENGTH]; mpz_t *coeffs = bs->cf_qq[bs->hm[i][COEFFS]]; for (j = 0; j < len; ++j) { mpz_clear(coeffs[j]); } free(bs->cf_qq[bs->hm[i][COEFFS]]); bs->cf_qq[bs->hm[i][COEFFS]] = NULL; free(bs->hm[i]); bs->hm[i] = NULL; } } /* signatures */ free(bs->sm); bs->sm = NULL; free(bs->si); bs->si = NULL; bs->ld = bs->lo = bs->lml = 0; } void free_basis( bs_t **bsp ) { full_free_hash_table(&((*bsp)->ht)); free_basis_without_hash_table(bsp); } void free_basis_and_only_local_hash_table_data( bs_t **bsp ) { free_hash_table(&((*bsp)->ht)); free_basis_without_hash_table(bsp); } void free_basis_without_hash_table( bs_t **bsp ) { len_t i, j, len; bs_t *bs = *bsp; if (bs->cf_8) { for (i = 0; i < bs->ld; ++i) { free(bs->cf_8[i]); free(bs->hm[i]); } free(bs->cf_8); bs->cf_8 = NULL; free(bs->hm); bs->hm = NULL; } if (bs->cf_16) { for (i = 0; i < bs->ld; ++i) { free(bs->cf_16[i]); free(bs->hm[i]); } free(bs->cf_16); bs->cf_16 = NULL; free(bs->hm); bs->hm = NULL; } if (bs->cf_32) { for (i = 0; i < bs->ld; ++i) { free(bs->cf_32[i]); free(bs->hm[i]); } free(bs->cf_32); bs->cf_32 = NULL; free(bs->hm); bs->hm = NULL; } if (bs->cf_qq) { for (i = 0; i < bs->ld; ++i) { len = bs->hm[i][LENGTH]; mpz_t *coeffs = bs->cf_qq[bs->hm[i][COEFFS]]; for (j = 0; j < len; ++j) { mpz_clear(coeffs[j]); } free(bs->cf_qq[bs->hm[i][COEFFS]]); free(bs->hm[i]); } free(bs->cf_qq); bs->cf_qq = NULL; free(bs->hm); bs->hm = NULL; } free(bs->lmps); bs->lmps = NULL; free(bs->lm); bs->lm = NULL; free(bs->red); bs->red = NULL; /* signatures */ free(bs->sm); bs->sm = NULL; free(bs->si); bs->si = NULL; free(bs); bs = NULL; *bsp = bs; } bs_t *initialize_basis( md_t *md ) { bs_t *bs = (bs_t *)calloc(1, sizeof(bs_t)); /* initialize meta data */ bs->lo = 0; bs->ld = 0; bs->lml = 0; bs->constant = 0; bs->sz = md->init_bs_sz; bs->mltdeg = 0; bs->ht = initialize_basis_hash_table(md); /* initialize basis elements data */ bs->hm = (hm_t **)malloc((unsigned long)bs->sz * sizeof(hm_t *)); bs->lm = (sdm_t *)malloc((unsigned long)bs->sz * sizeof(sdm_t)); bs->lmps = (bl_t *)malloc((unsigned long)bs->sz * sizeof(bl_t)); bs->red = (int8_t *)calloc((unsigned long)bs->sz, sizeof(int8_t)); /* signature-based groebner basis computation? */ if (md->use_signatures > 0) { bs->sm = (sm_t *)malloc((unsigned long)bs->sz * sizeof(sm_t)); bs->si = (si_t *)malloc((unsigned long)bs->sz * sizeof(si_t)); } /* initialize coefficients depending on ground field */ switch (md->ff_bits) { case 8: bs->cf_8 = (cf8_t **)malloc((unsigned long)bs->sz * sizeof(cf8_t *)); break; case 16: bs->cf_16 = (cf16_t **)malloc((unsigned long)bs->sz * sizeof(cf16_t *)); break; case 32: bs->cf_32 = (cf32_t **)malloc((unsigned long)bs->sz * sizeof(cf32_t *)); break; case 0: bs->cf_qq = (mpz_t **)malloc((unsigned long)bs->sz * sizeof(mpz_t *)); break; default: exit(1); } return bs; } void check_enlarge_basis( bs_t *bs, const len_t added, const md_t * const st ) { if (bs->ld + added >= bs->sz) { bs->sz = bs->sz * 2 > bs->ld + added ? bs->sz * 2 : bs->ld + added; bs->hm = realloc(bs->hm, (unsigned long)bs->sz * sizeof(hm_t *)); memset(bs->hm+bs->ld, 0, (unsigned long)(bs->sz-bs->ld) * sizeof(hm_t *)); bs->lm = realloc(bs->lm, (unsigned long)bs->sz * sizeof(sdm_t)); memset(bs->lm+bs->ld, 0, (unsigned long)(bs->sz-bs->ld) * sizeof(sdm_t)); bs->lmps = realloc(bs->lmps, (unsigned long)bs->sz * sizeof(bl_t)); memset(bs->lmps+bs->ld, 0, (unsigned long)(bs->sz-bs->ld) * sizeof(bl_t)); bs->red = realloc(bs->red, (unsigned long)bs->sz * sizeof(int8_t)); memset(bs->red+bs->ld, 0, (unsigned long)(bs->sz-bs->ld) * sizeof(int8_t)); switch (st->ff_bits) { case 8: bs->cf_8 = realloc(bs->cf_8, (unsigned long)bs->sz * sizeof(cf8_t *)); memset(bs->cf_8+bs->ld, 0, (unsigned long)(bs->sz-bs->ld) * sizeof(cf8_t *)); break; case 16: bs->cf_16 = realloc(bs->cf_16, (unsigned long)bs->sz * sizeof(cf16_t *)); memset(bs->cf_16+bs->ld, 0, (unsigned long)(bs->sz-bs->ld) * sizeof(cf16_t *)); break; case 32: bs->cf_32 = realloc(bs->cf_32, (unsigned long)bs->sz * sizeof(cf32_t *)); memset(bs->cf_32+bs->ld, 0, (unsigned long)(bs->sz-bs->ld) * sizeof(cf32_t *)); break; case 0: bs->cf_qq = realloc(bs->cf_qq, (unsigned long)bs->sz * sizeof(mpz_t *)); break; default: exit(1); } } } /* finite field stuff -- 8 bit */ static inline void normalize_initial_basis_ff_8( bs_t *bs, const uint32_t fc ) { len_t i, j; int64_t tmp1, tmp2, tmp3, tmp4; cf8_t **cf = bs->cf_8; hm_t * const *hm = bs->hm; const bl_t ld = bs->ld; const int16_t fc8 = (int16_t)fc; for (i = 0; i < ld; ++i) { cf8_t *row = cf[hm[i][COEFFS]]; const uint8_t inv = mod_p_inverse_8((int16_t)row[0], (int16_t)fc8); const len_t os = hm[i][PRELOOP]; const len_t len = hm[i][LENGTH]; for (j = 0; j < os; ++j) { tmp1 = ((int64_t)row[j] * inv) % fc8; tmp1 += (tmp1 >> 63) & fc8; row[j] = (cf8_t)tmp1; } for (j = os; j < len; j += UNROLL) { tmp1 = ((int64_t)row[j] * inv) % fc8; tmp2 = ((int64_t)row[j+1] * inv) % fc8; tmp3 = ((int64_t)row[j+2] * inv) % fc8; tmp4 = ((int64_t)row[j+3] * inv) % fc8; tmp1 += (tmp1 >> 63) & fc8; tmp2 += (tmp2 >> 63) & fc8; tmp3 += (tmp3 >> 63) & fc8; tmp4 += (tmp4 >> 63) & fc8; row[j] = (cf8_t)tmp1; row[j+1] = (cf8_t)tmp2; row[j+2] = (cf8_t)tmp3; row[j+3] = (cf8_t)tmp4; } } } /* finite field stuff -- 16 bit */ static inline void normalize_initial_basis_ff_16( bs_t *bs, const uint32_t fc ) { len_t i, j; int64_t tmp1, tmp2, tmp3, tmp4; cf16_t **cf = bs->cf_16; hm_t * const *hm = bs->hm; const bl_t ld = bs->ld; const int32_t fc16 = (int32_t)fc; for (i = 0; i < ld; ++i) { cf16_t *row = cf[hm[i][COEFFS]]; const uint16_t inv = mod_p_inverse_16((int32_t)row[0], (int32_t)fc16); const len_t os = hm[i][PRELOOP]; const len_t len = hm[i][LENGTH]; for (j = 0; j < os; ++j) { tmp1 = ((int64_t)row[j] * inv) % fc16; tmp1 += (tmp1 >> 63) & fc16; row[j] = (cf16_t)tmp1; } for (j = os; j < len; j += UNROLL) { tmp1 = ((int64_t)row[j] * inv) % fc16; tmp2 = ((int64_t)row[j+1] * inv) % fc16; tmp3 = ((int64_t)row[j+2] * inv) % fc16; tmp4 = ((int64_t)row[j+3] * inv) % fc16; tmp1 += (tmp1 >> 63) & fc16; tmp2 += (tmp2 >> 63) & fc16; tmp3 += (tmp3 >> 63) & fc16; tmp4 += (tmp4 >> 63) & fc16; row[j] = (cf16_t)tmp1; row[j+1] = (cf16_t)tmp2; row[j+2] = (cf16_t)tmp3; row[j+3] = (cf16_t)tmp4; } } } /* finite field stuff -- 32 bit */ static inline void normalize_initial_basis_ff_32( bs_t *bs, const uint32_t fc ) { len_t i, j; int64_t tmp1, tmp2, tmp3, tmp4; cf32_t **cf = bs->cf_32; hm_t * const *hm = bs->hm; const bl_t ld = bs->ld; for (i = 0; i < ld; ++i) { cf32_t *row = cf[hm[i][COEFFS]]; const uint32_t inv = mod_p_inverse_32((int64_t)row[0], (int64_t)fc); const len_t os = hm[i][PRELOOP]; const len_t len = hm[i][LENGTH]; for (j = 0; j < os; ++j) { tmp1 = ((int64_t)row[j] * inv) % fc; tmp1 += (tmp1 >> 63) & fc; row[j] = (cf32_t)tmp1; } for (j = os; j < len; j += UNROLL) { tmp1 = ((int64_t)row[j] * inv) % fc; tmp2 = ((int64_t)row[j+1] * inv) % fc; tmp3 = ((int64_t)row[j+2] * inv) % fc; tmp4 = ((int64_t)row[j+3] * inv) % fc; tmp1 += (tmp1 >> 63) & fc; tmp2 += (tmp2 >> 63) & fc; tmp3 += (tmp3 >> 63) & fc; tmp4 += (tmp4 >> 63) & fc; row[j] = (cf32_t)tmp1; row[j+1] = (cf32_t)tmp2; row[j+2] = (cf32_t)tmp3; row[j+3] = (cf32_t)tmp4; } } } /* characteristic zero stuff */ bs_t *copy_basis_mod_p( const bs_t * const gbs, const md_t *const st ) { len_t i, j, idx; /* set field characteristic */ unsigned long prime = (unsigned long)st->fc; /* initialize basis */ bs_t *bs = (bs_t *)calloc(1, sizeof(bs_t)); bs->lo = gbs->lo; bs->ld = gbs->ld; bs->lml = gbs->lml; bs->sz = gbs->sz; bs->constant = gbs->constant; if (st->f4_qq_round != 1) { bs->ht = copy_hash_table(gbs->ht); } else { bs->ht = gbs->ht; } bs->hm = (hm_t **)malloc((unsigned long)bs->sz * sizeof(hm_t *)); bs->lm = (sdm_t *)malloc((unsigned long)bs->sz * sizeof(sdm_t)); bs->lmps = (bl_t *)malloc((unsigned long)bs->sz * sizeof(bl_t)); bs->red = (int8_t *)calloc((unsigned long)bs->sz, sizeof(int8_t)); /* copy data */ memcpy(bs->lm, gbs->lm, (unsigned long)bs->sz * sizeof(sdm_t)); memcpy(bs->lmps, gbs->lmps, (unsigned long)bs->sz * sizeof(bl_t)); memcpy(bs->red, gbs->red, (unsigned long)bs->sz * sizeof(int8_t)); if (st->use_signatures > 0) { memcpy(bs->sm, gbs->sm, (unsigned long)bs->sz * sizeof(sm_t)); memcpy(bs->si, gbs->si, (unsigned long)bs->sz * sizeof(si_t)); } /* copy monomials */ for (i = 0; i < bs->ld; ++i) { bs->hm[i] = (hm_t *)malloc(((unsigned long)gbs->hm[i][LENGTH]+OFFSET) * sizeof(hm_t)); memcpy(bs->hm[i], gbs->hm[i], ((unsigned long)gbs->hm[i][LENGTH]+OFFSET) * sizeof(hm_t)); } /* copy coefficients */ switch (st->ff_bits) { case 8: bs->cf_8 = (cf8_t **)malloc((unsigned long)bs->sz * sizeof(cf8_t *)); for (i = 0; i < bs->ld; ++i) { idx = gbs->hm[i][COEFFS]; bs->cf_8[idx] = (cf8_t *)malloc((unsigned long)(gbs->hm[i][LENGTH]) * sizeof(cf8_t)); for (j = 0; j < gbs->hm[i][LENGTH]; ++j) { bs->cf_8[idx][j] = (cf8_t)mpz_fdiv_ui(gbs->cf_qq[idx][j], prime); } } break; case 16: bs->cf_16 = (cf16_t **)malloc((unsigned long)bs->sz * sizeof(cf16_t *)); for (i = 0; i < bs->ld; ++i) { idx = gbs->hm[i][COEFFS]; bs->cf_16[idx] = (cf16_t *)malloc((unsigned long)(gbs->hm[i][LENGTH]) * sizeof(cf16_t)); for (j = 0; j < gbs->hm[i][LENGTH]; ++j) { bs->cf_16[idx][j] = (cf16_t)mpz_fdiv_ui(gbs->cf_qq[idx][j], prime); } } break; case 32: bs->cf_32 = (cf32_t **)malloc((unsigned long)bs->sz * sizeof(cf32_t *)); for (i = 0; i < bs->ld; ++i) { idx = gbs->hm[i][COEFFS]; bs->cf_32[idx] = (cf32_t *)malloc((unsigned long)(gbs->hm[i][LENGTH]) * sizeof(cf32_t)); for (j = 0; j < gbs->hm[i][LENGTH]; ++j) { bs->cf_32[idx][j] = (cf32_t)mpz_fdiv_ui(gbs->cf_qq[idx][j], prime); } } break; default: exit(1); } return bs; } void remove_content_of_initial_basis( bs_t *bs ) { len_t i, j; mpz_t **cf = bs->cf_qq; hm_t * const *hm = bs->hm; const bl_t ld = bs->ld; mpz_t content; mpz_init(content); /* compute content, i.e. gcd of all coefficients */ i = 0; next_poly: for (; i < ld; ++i) { mpz_t *row = cf[hm[i][COEFFS]]; mpz_set(content, row[0]); const len_t os = hm[i][PRELOOP]; const len_t len = hm[i][LENGTH]; if (mpz_cmp_si(content, 0) != 0) { for (j = 1; j < len; ++j) { mpz_gcd(content, content, row[j]); if (mpz_cmp_si(content, 1) == 0) { i++; goto next_poly; } } /* remove content */ for (j = 0; j < os; ++j) { mpz_divexact(row[j], row[j], content); } for (; j < len; j += UNROLL) { mpz_divexact(row[j], row[j], content); mpz_divexact(row[j+1], row[j+1], content); mpz_divexact(row[j+2], row[j+2], content); mpz_divexact(row[j+3], row[j+3], content); } } } mpz_clear(content); /* make lead coefficient positive */ for (i = 0; i < ld; ++i) { mpz_t *row = cf[hm[i][COEFFS]]; const len_t os = hm[i][PRELOOP]; const len_t len = hm[i][LENGTH]; if (mpz_sgn(row[0]) == -1) { for (j = 0; j < os; ++j) { mpz_neg(row[j], row[j]); } for (; j < len; j += UNROLL) { mpz_neg(row[j], row[j]); mpz_neg(row[j+1], row[j+1]); mpz_neg(row[j+2], row[j+2]); mpz_neg(row[j+3], row[j+3]); } } } } msolve-0.6.5/src/neogb/basis.h000066400000000000000000000024571456710632100161770ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef GB_BASIS_H #define GB_BASIS_H #include "data.h" void free_basis_without_hash_table( bs_t **bsp ); void free_basis_and_only_local_hash_table_data( bs_t **bsp ); void free_basis( bs_t **bsp ); void remove_content_of_initial_basis( bs_t *bs ); bs_t *initialize_basis( md_t *md ); bs_t *copy_basis_mod_p( const bs_t * const gbs, const md_t * const st ); void check_enlarge_basis( bs_t *bs, const len_t added, const md_t *st ); #endif msolve-0.6.5/src/neogb/convert.c000066400000000000000000000625631456710632100165550ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "data.h" /* after calling this procedure we have column indices instead of exponent * hashes in the polynomials resp. rows. moreover, we have sorted each row * by pivots / non-pivots. thus we get already an A|B splicing of the * initial matrix. this is a first step for receiving a full GBLA matrix. */ static void convert_multipliers_to_columns( hi_t **hcmp, bs_t *sat, md_t *st, ht_t *ht ) { hl_t i; hi_t *hcm = *hcmp; /* clear ht-ev[0] */ memset(ht->ev[0], 0, (unsigned long)ht->nv * sizeof(exp_t)); /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* all elements in the sht hash table represent * exactly one column of the matrix */ hcm = realloc(hcm, (unsigned long)sat->ld * sizeof(hi_t)); for (i = 0; i < sat->ld; ++i) { hcm[i] = sat->hm[i][MULT]; } sort_r(hcm, (unsigned long)sat->ld, sizeof(hi_t), hcm_cmp, ht); /* printf("hcmm\n"); * for (int ii=0; iild; ++ii) { * printf("hcmm[%d] = %d | idx %u | ", ii, ht->hd[hcm[ii]].idx, hcm[ii]); * for (int jj = 0; jj < ht->nv; ++jj) { * printf("%d ", ht->ev[hcm[ii]][jj]); * } * printf("\n"); * } */ /* store the other direction (hash -> column) */ for (i = 0; i < sat->ld; ++i) { ht->hd[hcm[i]].idx = (hi_t)i; } /* map column positions to mul entries*/ for (i = 0; i < sat->ld; ++i) { sat->hm[i][MULT] = ht->hd[sat->hm[i][MULT]].idx; } /* timings */ ct1 = cputime(); rt1 = realtime(); st->convert_ctime += ct1 - ct0; st->convert_rtime += rt1 - rt0; *hcmp = hcm; } static void convert_hashes_to_columns_sat( mat_t *mat, bs_t *sat, md_t *st, ht_t *sht ) { hl_t i; hi_t j, k; hm_t *row; int64_t nterms = 0; hi_t *hcm = st->hcm; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); len_t hi; const len_t mnr = mat->nr; const hl_t esld = sht->eld; hd_t *hds = sht->hd; hm_t **rrows = mat->rr; /* all elements in the sht hash table represent * exactly one column of the matrix */ hcm = realloc(hcm, (esld-1) * sizeof(hi_t)); for (k = 0, j = 0, i = 1; i < esld; ++i) { hi = hds[i].idx; hcm[j++] = i; if (hi == 2) { k++; } } sort_r(hcm, (unsigned long)j, sizeof(hi_t), hcm_cmp, sht); /* printf("hcm\n"); * for (int ii=0; iiev[hcm[ii]][DEG]+sht->ev[hcm[ii]][sht->ebl]); * for (int jj = 0; jj < sht->evl; ++jj) { * printf("%d ", sht->ev[hcm[ii]][jj]); * } * printf("\n"); * } */ mat->ncl = k; mat->ncr = (len_t)esld - 1 - mat->ncl; st->num_rowsred += sat->ld; /* store the other direction (hash -> column) */ const hi_t ld = (hi_t)(esld - 1); for (k = 0; k < ld; ++k) { hds[hcm[k]].idx = (hi_t)k; } /* map column positions to reducer matrix */ #pragma omp parallel for num_threads(st->nthrds) private(k, j, row) for (k = 0; k < mat->nru; ++k) { const len_t os = rrows[k][PRELOOP]; const len_t len = rrows[k][LENGTH]; row = rrows[k] + OFFSET; for (j = 0; j < os; ++j) { row[j] = hds[row[j]].idx; } for (; j < len; j += UNROLL) { row[j] = hds[row[j]].idx; row[j+1] = hds[row[j+1]].idx; row[j+2] = hds[row[j+2]].idx; row[j+3] = hds[row[j+3]].idx; } } for (k = 0; k < mat->nru; ++k) { nterms += rrows[k][LENGTH]; } /* map column positions to saturation elements */ #pragma omp parallel for num_threads(st->nthrds) private(k, j, row) for (k = 0; k < sat->ld; ++k) { const len_t os = sat->hm[k][PRELOOP]; const len_t len = sat->hm[k][LENGTH]; row = sat->hm[k] + OFFSET; for (j = 0; j < os; ++j) { row[j] = hds[row[j]].idx; } for (; j < len; j += UNROLL) { row[j] = hds[row[j]].idx; row[j+1] = hds[row[j+1]].idx; row[j+2] = hds[row[j+2]].idx; row[j+3] = hds[row[j+3]].idx; } } for (k = 0; k < mat->nrl; ++k) { nterms += sat->hm[k][LENGTH]; } /* next we sort each row by the new colum order due * to known / unkown pivots */ /* NOTE: As strange as it may sound, we do not need to sort the rows. * When reducing, we copy them to dense rows, there we copy the coefficients * at the right place and reduce then. For the reducers itself it is not * important in which order the terms are represented as long as the first * term is the lead term, which is always true. Once a row is finally reduced * it is copied back to a sparse representation, now in the correct term * order since it is coming from the correctly sorted dense row. So all newly * added elements have all their terms sorted correctly w.r.t. the given * monomial order. */ /* compute density of matrix */ nterms *= 100; /* for percentage */ double density = (double)nterms / (double)mnr / (double)mat->nc; /* timings */ ct1 = cputime(); rt1 = realtime(); st->convert_ctime += ct1 - ct0; st->convert_rtime += rt1 - rt0; if (st->info_level > 1) { printf(" %7d x %-7d %8.2f%%", mat->nr + sat->ld, mat->nc, density); fflush(stdout); } st->hcm = hcm; } static void sba_convert_hashes_to_columns( hi_t **hcmp, smat_t *smat, md_t *st, ht_t *ht ) { len_t i, j, k; hm_t *row; int64_t nterms = 0; hi_t *hcm = *hcmp; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); const len_t nr = smat->cld; const hl_t eld = ht->eld; hd_t *hd = ht->hd; hm_t **cr = smat->cr; hcm = realloc(hcm, (unsigned long)eld * sizeof(hi_t)); k = 0; for (i = 0; i < nr; ++i) { const len_t len = SM_OFFSET + cr[i][SM_LEN]; for (j = SM_OFFSET; j < len; ++j) { if (hd[cr[i][j]].idx == 0) { hd[cr[i][j]].idx = 1; hcm[k++] = cr[i][j]; } } } hcm = realloc(hcm, (unsigned long)k * sizeof(hi_t)); sort_r(hcm, (unsigned long)k, sizeof(hi_t), hcm_cmp, ht); smat->nc = k; /* printf("hcm\n"); * for (int ii=0; iiev[hcm[ii]][DEG]+sht->ev[hcm[ii]][sht->ebl]); * for (int jj = 0; jj < sht->evl; ++jj) { * printf("%d ", sht->ev[hcm[ii]][jj]); * } * printf("\n"); * } */ /* store the other direction (hash -> column) */ const hi_t ld = k; for (i = 0; i < ld; ++i) { hd[hcm[i]].idx = (hi_t)i; } /* map column positions to matrix rows */ #pragma omp parallel for num_threads(st->nthrds) private(k, j, row) for (i = 0; i < nr; ++i) { const len_t os = cr[i][SM_PRE]; const len_t len = cr[i][SM_LEN]; row = cr[i] + SM_OFFSET; for (j = 0; j < os; ++j) { row[j] = hd[row[j]].idx; } for (; j < len; j += UNROLL) { row[j] = hd[row[j]].idx; row[j+1] = hd[row[j+1]].idx; row[j+2] = hd[row[j+2]].idx; row[j+3] = hd[row[j+3]].idx; } nterms += len; } /* compute density of matrix */ nterms *= 100; /* for percentage */ double density = (double)nterms / (double)nr / (double)smat->nc; /* timings */ ct1 = cputime(); rt1 = realtime(); st->convert_ctime += ct1 - ct0; st->convert_rtime += rt1 - rt0; if (st->info_level > 1) { printf("%4d %7d x %-7d %8.2f%%", smat->cd, smat->cld, smat->nc, density); fflush(stdout); } *hcmp = hcm; } static void convert_hashes_to_columns( mat_t *mat, md_t *st, ht_t *sht ) { hl_t i; hi_t j, k; hm_t *row; int64_t nterms = 0; hi_t *hcm = st->hcm; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); len_t hi; const len_t mnr = mat->nr; const hl_t esld = sht->eld; hd_t *hds = sht->hd; hm_t **rrows = mat->rr; hm_t **trows = mat->tr; /* all elements in the sht hash table represent * exactly one column of the matrix */ hcm = realloc(hcm, (esld-1) * sizeof(hi_t)); for (k = 0, j = 0, i = 1; i < esld; ++i) { hi = hds[i].idx; hcm[j++] = i; if (hi == 2) { k++; } } sort_r(hcm, (unsigned long)j, sizeof(hi_t), hcm_cmp, sht); /* printf("hcm\n"); for (int ii=0; iiev[hcm[ii]][DEG]+sht->ev[hcm[ii]][sht->ebl]); for (int jj = 0; jj < sht->evl; ++jj) { printf("%d ", sht->ev[hcm[ii]][jj]); } printf("\n"); } */ mat->ncl = k; mat->ncr = (len_t)esld - 1 - mat->ncl; mat->nc = mat->ncl + mat->ncr; st->num_rowsred += mat->nrl; /* store the other direction (hash -> column) */ const hi_t ld = (hi_t)(esld - 1); for (k = 0; k < ld; ++k) { hds[hcm[k]].idx = (hi_t)k; } /* map column positions to matrix rows */ #pragma omp parallel for num_threads(st->nthrds) private(k, j, row) for (k = 0; k < mat->nru; ++k) { const len_t os = rrows[k][PRELOOP]; const len_t len = rrows[k][LENGTH]; row = rrows[k] + OFFSET; for (j = 0; j < os; ++j) { row[j] = hds[row[j]].idx; } for (; j < len; j += UNROLL) { row[j] = hds[row[j]].idx; row[j+1] = hds[row[j+1]].idx; row[j+2] = hds[row[j+2]].idx; row[j+3] = hds[row[j+3]].idx; } } for (k = 0; k < mat->nru; ++k) { nterms += rrows[k][LENGTH]; } #pragma omp parallel for num_threads(st->nthrds) private(k, j, row) for (k = 0; k < mat->nrl; ++k) { const len_t os = trows[k][PRELOOP]; const len_t len = trows[k][LENGTH]; row = trows[k] + OFFSET; for (j = 0; j < os; ++j) { row[j] = hds[row[j]].idx; } for (; j < len; j += UNROLL) { row[j] = hds[row[j]].idx; row[j+1] = hds[row[j+1]].idx; row[j+2] = hds[row[j+2]].idx; row[j+3] = hds[row[j+3]].idx; } } for (k = 0; k < mat->nrl; ++k) { nterms += trows[k][LENGTH]; } /* next we sort each row by the new colum order due * to known / unkown pivots */ /* NOTE: As strange as it may sound, we do not need to sort the rows. * When reducing, we copy them to dense rows, there we copy the coefficients * at the right place and reduce then. For the reducers itself it is not * important in which order the terms are represented as long as the first * term is the lead term, which is always true. Once a row is finally reduced * it is copied back to a sparse representation, now in the correct term * order since it is coming from the correctly sorted dense row. So all newly * added elements have all their terms sorted correctly w.r.t. the given * monomial order. */ /* compute density of matrix */ nterms *= 100; /* for percentage */ double density = (double)nterms / (double)mnr / (double)ld; /* timings */ ct1 = cputime(); rt1 = realtime(); st->convert_ctime += ct1 - ct0; st->convert_rtime += rt1 - rt0; if (st->info_level > 1) { printf(" %7d x %-7d %8.2f%%", mat->nr, mat->nc, density); fflush(stdout); } if ((int64_t)mat->nr * mat->nc > st->mat_max_nrows * st->mat_max_ncols) { st->mat_max_nrows = mat->nr; st->mat_max_ncols = mat->nc; st->mat_max_density = density; } st->hcm = hcm; } static void sba_convert_columns_to_hashes( smat_t *smat, const hi_t * const hcm ) { len_t i, j; for (i = 0; i < smat->cld; ++i) { const len_t len = smat->cr[i][SM_LEN] + SM_OFFSET; for (j = SM_OFFSET; j < len; ++j) { smat->cr[i][j] = hcm[smat->cr[i][j]]; } } } static void convert_columns_to_hashes( bs_t *bs, const md_t *md, const hi_t * const hcmm ) { len_t i, j; const hi_t *hcm = md->hcm; for (i = 0; i < bs->ld; ++i) { if (bs->hm[i] != NULL) { for (j = OFFSET; j < bs->hm[i][LENGTH]+OFFSET; ++j) { bs->hm[i][j] = hcm[bs->hm[i][j]]; } bs->hm[i][MULT] = hcmm[bs->hm[i][MULT]]; } } } /* add_kernel_elements_to_basis() is unused at the moment */ #if 0 static void add_kernel_elements_to_basis( bs_t *sat, bs_t *bs, bs_t *kernel, const ht_t * const ht, const hi_t * const hcm, md_t *st ) { len_t *terms = (len_t *)calloc((unsigned long)sat->ld, sizeof(len_t)); len_t nterms = 0; len_t i, j, k; len_t ctr = 0; const len_t bld = bs->ld; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* fix size of basis for entering new elements directly */ check_enlarge_basis(bs, kernel->ld); /* we need to sort the kernel elements first (in order to track * redundancy correctly) */ hm_t **rows = (hm_t **)calloc((unsigned long)kernel->ld, sizeof(hm_t *)); k = 0; for (i = 0; i < kernel->ld; ++i) { /* printf("kernel[%u] = %p\n", i, kernel->hm[i]); */ rows[k++] = kernel->hm[i]; kernel->hm[i] = NULL; } sort_matrix_rows_increasing(rows, k); /* only for 32 bit at the moment */ for (i = 0; i < kernel->ld; ++i) { bs->cf_32[bld+ctr] = kernel->cf_32[rows[i][COEFFS]]; kernel->cf_32[rows[i][COEFFS]] = NULL; bs->hm[bld+ctr] = rows[i]; bs->hm[bld+ctr][COEFFS] = bld+ctr; j = OFFSET; next_j: for (; j < bs->hm[bld+ctr][LENGTH]+OFFSET; ++j) { bs->hm[bld+ctr][j] = hcm[bs->hm[bld+ctr][j]]; if (nterms != 0) { for (int kk = 0; kk < nterms; ++kk) { if (terms[kk] == bs->hm[bld+ctr][j]) { j++; goto next_j; } } } terms[nterms] = bs->hm[bld+ctr][j]; nterms++; } if (ht->ev[bs->hm[bld+ctr][OFFSET]][DEG] == 0) { bs->constant = 1; } /* printf("new element from kernel (%u): length %u | ", bld+ctr, bs->hm[bld+ctr][LENGTH]); * for (int kk=0; kkhm[bld+ctr][LENGTH]; ++kk) { * printf("%u | ", bs->cf_32[bld+ctr][kk]); * printf("%u | ", ht->ev[bs->hm[bld+ctr][OFFSET+kk]][DEG]); * for (int jj=0; jj < ht->nv; ++jj) { * printf("%u ", ht->ev[bs->hm[bld+ctr][OFFSET+kk]][jj]); * } * printf(" || "); * } * printf("\n"); */ ctr++; } /* printf("%u of %u terms are used for kernel elements, %.2f\n", nterms, sat->ld, (float)nterms / (float)sat->ld); */ free(terms); free(rows); rows = NULL; /* timings */ ct1 = cputime(); rt1 = realtime(); st->convert_ctime += ct1 - ct0; st->convert_rtime += rt1 - rt0; } #endif static void return_normal_forms_to_basis( mat_t *mat, bs_t *bs, ht_t *bht, const ht_t * const sht, const hi_t * const hcm, md_t *st ) { len_t i; const len_t np = mat->np; /* timings */ double ct = cputime(); double rt = realtime(); free_basis_elements(bs); /* fix size of basis for entering new elements directly */ check_enlarge_basis(bs, mat->np, st); hm_t **rows = mat->tr; /* only for 32 bit at the moment */ for (i = 0; i < np; ++i) { if (rows[i] != NULL) { insert_in_basis_hash_table_pivots(rows[i], bht, sht, hcm, st); switch (st->ff_bits) { case 0: bs->cf_qq[bs->ld] = mat->cf_qq[rows[i][COEFFS]]; break; case 8: bs->cf_8[bs->ld] = mat->cf_8[rows[i][COEFFS]]; break; case 16: bs->cf_16[bs->ld] = mat->cf_16[rows[i][COEFFS]]; break; case 32: bs->cf_32[bs->ld] = mat->cf_32[rows[i][COEFFS]]; break; default: bs->cf_32[bs->ld] = mat->cf_32[rows[i][COEFFS]]; break; } rows[i][COEFFS] = bs->ld; bs->hm[bs->ld] = rows[i]; } else { switch (st->ff_bits) { case 0: bs->cf_qq[bs->ld] = NULL; break; case 8: bs->cf_8[bs->ld] = NULL; break; case 16: bs->cf_16[bs->ld] = NULL; break; case 32: bs->cf_32[bs->ld] = NULL; break; default: bs->cf_32[bs->ld] = NULL; break; } bs->hm[bs->ld] = NULL; } bs->lmps[bs->ld] = bs->ld; bs->lml++; bs->ld++; } /* timings */ st->convert_ctime += cputime() - ct; st->convert_rtime += realtime() - rt; } static void convert_sparse_matrix_rows_to_basis_elements( const int sort, mat_t *mat, bs_t *bs, ht_t *bht, const ht_t * const sht, md_t *st ) { len_t i, j, k; deg_t deg; const len_t bl = bs->ld; const len_t np = mat->np; hi_t *hcm = st->hcm; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* fix size of basis for entering new elements directly */ check_enlarge_basis(bs, mat->np, st); hm_t **rows = mat->tr; deg_t pairs_deg = sht->hd[hcm[0]].deg; switch_hcm_data_to_basis_hash_table(hcm, bht, mat, sht); #pragma omp parallel for num_threads(st->nthrds) \ private(i, j, k) for (k = 0; k < np; ++k) { /* We first insert the highest leading monomial element to the basis * for a better Gebauer-Moeller application when updating the pair * set later on. */ if (sort == -1) { i = np - 1 - k; } else { i = k; } const len_t len = rows[i][LENGTH]+OFFSET; for (j = OFFSET; j < len; ++j) { rows[i][j] = hcm[rows[i][j]]; } deg = bht->hd[rows[i][OFFSET]].deg; if (st->nev > 0) { const len_t len = rows[i][LENGTH]+OFFSET; for (j = OFFSET+1; j < len; ++j) { if (deg < bht->hd[rows[i][j]].deg) { deg = bht->hd[rows[i][j]].deg; } } } switch (st->ff_bits) { case 0: bs->cf_qq[bl+k] = mat->cf_qq[rows[i][COEFFS]]; break; case 8: bs->cf_8[bl+k] = mat->cf_8[rows[i][COEFFS]]; break; case 16: bs->cf_16[bl+k] = mat->cf_16[rows[i][COEFFS]]; break; case 32: bs->cf_32[bl+k] = mat->cf_32[rows[i][COEFFS]]; break; default: bs->cf_32[bl+k] = mat->cf_32[rows[i][COEFFS]]; break; } rows[i][COEFFS] = bl+k; bs->hm[bl+k] = rows[i]; bs->hm[bl+k][DEG] = deg; if (deg == 0) { bs->constant = 1; } #if 0 if (st->ff_bits == 32) { printf("new element (%u): length %u | degree %d | ", bl+k, bs->hm[bl+k][LENGTH], bs->hm[bl+k][DEG]); int kk = 0; for (int kk=0; kkhm[bl+k][LENGTH]; ++kk) { printf("%u | ", bs->cf_32[bl+k][kk]); for (int jj=0; jj < bht->evl; ++jj) { printf("%u ", bht->ev[bs->hm[bl+k][OFFSET+kk]][jj]); } printf(" || "); } printf("\n"); } if (st->ff_bits == 16) { printf("new element (%u): length %u | degree %d (difference %d) | ", bl+k, bs->hm[bl+k][LENGTH], bs->hm[bl+k][DEG], bs->hm[bl+k][DEG] - bht->hd[bs->hm[bl+k][OFFSET]].deg); int kk = 0; for (int kk=0; kkhm[bl+k][LENGTH]; ++kk) { printf("%u | ", bs->cf_16[bl+k][kk]); for (int jj=0; jj < bht->evl; ++jj) { printf("%u ", bht->ev[bs->hm[bl+k][OFFSET+kk]][jj]); } printf(" || "); } printf("\n"); } if (st->ff_bits == 8) { printf("new element (%u): length %u | degree %d (difference %d) | ", bl+k, bs->hm[bl+k][LENGTH], bs->hm[bl+k][DEG], bs->hm[bl+k][DEG] - bht->hd[bs->hm[bl+k][OFFSET]].deg); int kk = 0; for (int kk=0; kkhm[bl+k][LENGTH]; ++kk) { printf("%u | ", bs->cf_8[bl+k][kk]); for (int jj=0; jj < bht->evl; ++jj) { printf("%u ", bht->ev[bs->hm[bl+k][OFFSET+kk]][jj]); } printf(" || "); } printf("\n"); } #endif } /* last element has smallest leading monomial, i.e. also the smallest possible degree, so check with this for a degree fall */ if ( st->trace_level != APPLY_TRACER && st->in_final_reduction_step != 1 && st->homogeneous == 0 && st->min_deg_in_first_deg_fall == INT32_MAX && deg < pairs_deg ) { st->min_deg_in_first_deg_fall = deg; } /* timings */ ct1 = cputime(); rt1 = realtime(); st->convert_ctime += ct1 - ct0; st->convert_rtime += rt1 - rt0; } static void convert_sparse_matrix_rows_to_basis_elements_use_sht( const int sort, mat_t *mat, bs_t *bs, const ht_t * const sht, md_t *st ) { len_t i, j, k; deg_t deg; hm_t *row; const len_t bl = bs->ld; const len_t np = mat->np; const hi_t * const hcm = st->hcm; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* fix size of basis for entering new elements directly */ check_enlarge_basis(bs, mat->np, st); hm_t **rows = mat->tr; for (k = 0; k < np; ++k) { /* We first insert the highest leading monomial element to the basis * for a better Gebauer-Moeller application when updating the pair * set later on. */ if (sort == -1) { i = np - 1 - k; } else { i = k; } row = rows[i]; deg = sht->hd[hcm[rows[i][OFFSET]]].deg; const len_t len = rows[i][LENGTH]+OFFSET; if (st->nev == 0) { for (j = OFFSET; j < len; ++j) { row[j] = hcm[row[j]]; } } else { for (j = OFFSET; j < len; ++j) { row[j] = hcm[row[j]]; if (deg < sht->hd[row[j]].deg) { deg = sht->hd[row[j]].deg; } } } switch (st->ff_bits) { case 0: bs->cf_qq[bl+k] = mat->cf_qq[rows[i][COEFFS]]; break; case 8: bs->cf_8[bl+k] = mat->cf_8[rows[i][COEFFS]]; break; case 16: bs->cf_16[bl+k] = mat->cf_16[rows[i][COEFFS]]; break; case 32: bs->cf_32[bl+k] = mat->cf_32[rows[i][COEFFS]]; break; default: bs->cf_32[bl+k] = mat->cf_32[rows[i][COEFFS]]; break; } rows[i][COEFFS] = bl+k; bs->hm[bl+k] = rows[i]; bs->hm[bl+k][DEG] = deg; if (deg == 0) { bs->constant = 1; } #if 0 if (st->ff_bits == 32) { printf("new element (%u): length %u | degree %d | ", bl+k, bs->hm[bl+k][LENGTH], bs->hm[bl+k][DEG]); int kk = 0; /* for (int kk=0; kkhm[bl+k][LENGTH]; ++kk) { */ printf("%u | ", bs->cf_32[bl+k][kk]); for (int jj=0; jj < sht->evl; ++jj) { printf("%u ", sht->ev[bs->hm[bl+k][OFFSET+kk]][jj]); } /* printf(" || "); * } */ printf("\n"); } #endif } /* timings */ ct1 = cputime(); rt1 = realtime(); st->convert_ctime += ct1 - ct0; st->convert_rtime += rt1 - rt0; } msolve-0.6.5/src/neogb/data.c000066400000000000000000000077201456710632100160000ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "data.h" /* function pointers */ /* bs_t *(*initialize_basis)( * const int32_t ngens * ); */ void (*normalize_initial_basis)( bs_t *bs, const uint32_t fc ); int (*initial_input_cmp)( const void *a, const void *b, void *ht ); int (*initial_gens_cmp)( const void *a, const void *b, void *ht ); int (*monomial_cmp)( const hi_t a, const hi_t b, const ht_t *ht ); int (*spair_cmp)( const void *a, const void *b, void *htp ); int (*hcm_cmp)( const void *a, const void *b, void *htp ); /* linear algebra routines */ void (*sba_linear_algebra)( smat_t *smat, crit_t *syz, md_t *st, const ht_t * const ht ); void (*exact_linear_algebra)( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ); void (*linear_algebra)( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ); int (*application_linear_algebra)( mat_t *mat, const bs_t * const bs, md_t *st ); void (*trace_linear_algebra)( trace_t *trace, mat_t *mat, const bs_t * const bs, md_t *st ); void (* interreduce_matrix_rows)( mat_t *mat, bs_t *bs, md_t *st, int free_basis ); cf32_t *(*reduce_dense_row_by_old_pivots_ff_32)( int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t * const * const pivs, const hi_t dpiv, const uint32_t fc ); hm_t *(*sba_reduce_dense_row_by_known_pivots_sparse_ff_32)( int64_t *dr, smat_t *smat, hm_t *const *pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const hm_t sm, /* signature monomial of row reduced */ const len_t si, /* signature index of row reduced */ const len_t ri, /* index of row in matrix */ md_t *st ); hm_t *(*reduce_dense_row_by_known_pivots_sparse_ff_32)( int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t *const *pivs, const hi_t dpiv, const hm_t tmp_pos, const len_t mh, /* multiplier hash for tracing */ const len_t bi, /* basis index of generating element */ const len_t tr, /* trace data? */ md_t *st ); hm_t *(*trace_reduce_dense_row_by_known_pivots_sparse_ff_32)( rba_t *rba, int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t *const *pivs, const hi_t dpiv, const hm_t tmp_pos, const len_t mh, const len_t bi, md_t *st ); cf32_t *(*reduce_dense_row_by_all_pivots_ff_32)( int64_t *dr, mat_t *mat, const bs_t * const bs, len_t *pc, hm_t *const *pivs, cf32_t *const *dpivs, const uint32_t fc ); cf32_t *(*reduce_dense_row_by_dense_new_pivots_ff_32)( int64_t *dr, len_t *pc, cf32_t * const * const pivs, const len_t ncr, const uint32_t fc ); msolve-0.6.5/src/neogb/data.h000066400000000000000000000454601456710632100160100ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef GB_DATA_H #define GB_DATA_H #define _GNU_SOURCE #include #include #include #include #include /* for memset et al. */ #include #include /* check if OpenMP is available */ #ifdef _OPENMP #include #else typedef int omp_int_t; inline omp_int_t omp_get_thread_num(void) { return 0;} inline omp_int_t omp_get_max_threads(void) { return 1;} #endif #define PARALLEL_HASHING 0 #define ORDER_COLUMNS 1 /* loop unrolling in sparse linear algebra: * we store the offset of the first elements not unrolled * in the second entry of the sparse row resp. sparse polynomial. * NOTE: if one changes UNROLL then also code needs to be changed: * the unrolled loops are hardcoded to 4 at the moment */ #define UNROLL 4 /* we store some more information in the row arrays, * real data starts at index OFFSET */ #define OFFSET 6 /* real data starts at OFFSET */ #define LENGTH (OFFSET-1) /* length of the row */ #define PRELOOP (OFFSET-2) /* length of not unrolled loop part */ #define COEFFS (OFFSET-3) /* index of corresponding coefficient vector */ #define MULT (OFFSET-4) /* hash of multiplier (for tracing and saturation) */ #define BINDEX (OFFSET-5) /* basis index of element (for tracing) */ #define DEG (OFFSET-6) /* the first entry in each exponent vector * stores the total degree of the polynomial */ /* there is a different prelude with meta data for signature based matrices */ #define SM_OFFSET 5 /* real data starts at SIGOFFSET for signature * based comptutations */ #define SM_LEN (SM_OFFSET-1) /* signature meta data length of polynomial */ #define SM_PRE (SM_OFFSET-2) /* signature meta data preloop of polynomial */ #define SM_CFS (SM_OFFSET-3) /* index of corresponding coefficient array */ #define SM_SIDX (SM_OFFSET-4) /* index of signautre */ #define SM_SMON (SM_OFFSET-5) /* hash value of signature monomial */ /* computational data */ typedef uint8_t cf8_t; /* coefficient type finite field (8 bit) */ typedef uint16_t cf16_t; /* coefficient type finite field (16 bit) */ typedef uint32_t cf32_t; /* coefficient type finite field (32 bit) */ typedef uint32_t val_t; /* core values like hashes */ typedef val_t hi_t; /* index of hash table entries*/ typedef hi_t hm_t; /* hashed monomials for polynomial entries */ typedef hm_t sm_t; /* hashed monomial of signature */ typedef uint16_t si_t; /* index of signature */ typedef uint64_t hl_t; /* hash table length (maybe >= 2^32) */ /* like exponent hashes, etc. */ typedef uint32_t rba_t; /* reducer binary array */ typedef uint32_t ind_t; /* index in hash table structure */ typedef uint32_t sdm_t; /* short divmask for faster divisibility checks */ typedef uint32_t len_t; /* length type for different structures */ typedef uint16_t exp_t; /* exponent type */ typedef int32_t deg_t; /* (total) degree of polynomial */ typedef len_t bi_t; /* basis index of element */ typedef len_t bl_t; /* basis load */ typedef len_t pl_t; /* pair set load */ /* hash data structure */ typedef struct hd_t hd_t; struct hd_t { val_t val; sdm_t sdm; ind_t idx; deg_t deg; }; /* * Exponent vectors look the following for n variables: * * 1. If we use a non-block monomial order like DRL * [deg, exp_v1, ..., exp_vn] * -> length is n+1 * * 2. If we use a block elimination order with two blocks * of k variables and n-k variables * [deg_b1, exp_v1, ..., exp_vk, deg_b2, exp_vk+1, ..., exp_vn] * -> length is n+2 * * In any of the above situations nv will be n. * evl will be nv + 1 + (ebl != 0) where ebl is the number * of variables in the first variable block + 1 (for the degree of * this block) if we use an elimination block order, 0 otherwise. * */ /* hash table data structure */ typedef struct ht_t ht_t; struct ht_t { exp_t **ev; /* exponent vector */ hd_t *hd; /* hash data */ hi_t *hmap; /* hash map */ len_t elo; /* load of exponent vector before current step */ hl_t eld; /* load of exponent vector */ hl_t esz; /* size of exponent vector */ hl_t hsz; /* size of hash map, might be 2^32 */ len_t ebl; /* elimination block length: * degree + #elimination variables, * 0 if no elimination order */ len_t nv; /* number of variables */ len_t evl; /* real length of exponent vector, * includes degree (or two degrees * if an elimination order is used) */ sdm_t *dm; /* divisor map for divisibility checks */ len_t *dv; /* variables for divmask */ len_t ndv; /* number of variables for divmask */ len_t bpv; /* bits per variable in divmask */ val_t *rn; /* random numbers for hash generation */ uint32_t rsd; /* seed for random number generator */ }; /* S-pair types */ typedef enum {S_PAIR, GCD_PAIR, GEN_PAIR} spt_t; typedef struct spair_t spair_t; struct spair_t { hi_t lcm; bi_t gen1; bi_t gen2; deg_t deg; spt_t type; }; typedef struct ps_t ps_t; struct ps_t { len_t ld; len_t sz; spair_t *p; }; /* signature criteria structure, * at the moment we only store the lead terms (i e. signatures) */ typedef struct crit_t crit_t; struct crit_t { sdm_t *sdm; // array of shot divisor mask of signature monomial hm_t *hm; // array of hash value of the of the signature monomial len_t ld; // load of the corresponding arrays len_t sz; // allocated memory / size of the corresponding arrays }; /* basis stuff */ typedef struct bs_t bs_t; struct bs_t { bl_t ld; /* load of basis */ bl_t sz; /* size allocated for basis */ bl_t lo; /* load before current update */ bl_t constant; /* 1 if constant is found in basis */ deg_t mltdeg; /* maximal appearing degree in lead term in basis */ bl_t *lmps; /* position of non-redundant lead monomials in basis */ sdm_t *lm; /* non-redundant lead monomials as short divmask */ bl_t lml; /* number of lead monomials of non redundant elements in basis */ ht_t *ht; /* hash table for basis elements */ int8_t *red; /* tracks redundancy of basis elements */ hm_t **hm; /* hashed monomials representing exponents */ sm_t *sm; /* signatures for F5-style computations */ si_t *si; /* signatures index for F5-style computations */ cf8_t **cf_8; /* coefficients for finite fields (8 bit) */ cf16_t **cf_16; /* coefficients for finite fields (16 bit) */ cf32_t **cf_32; /* coefficients for finite fields (32 bit) */ mpz_t **cf_qq; /* coefficients for rationals (always multiplied such that the denominator is 1) */ }; /* matrix stuff */ typedef struct mat_t mat_t; struct mat_t { hm_t **tr; /* rows to be reduced of the matrix, only column */ /* entries, coefficients are handled via linking */ /* to coefficient arrays */ rba_t **rba; /* bit array for each row to be reduced storing */ /* if a reducer row is used during reduction. */ /* Thus we can reconstruct the trace for the */ /* rows not reduced to zero easily by bitwise */ /* AND operations on these bit arrays. */ hm_t **rr; /* reducer rows of the matrix, only column */ /* entries, coefficients are handled via linking */ /* to coefficient arrays. */ cf8_t **cf_8; /* coefficients for finite fields (8 bit) */ cf16_t **cf_16; /* coefficients for finite fields (16 bit) */ cf32_t **cf_32; /* coefficients for finite fields (32 bit) */ mpz_t **cf_qq; /* coefficients for rationals */ mpz_t **cf_ab_qq; /* coefficients for rationals */ len_t sz; /* number of rows allocated resp. size */ len_t np; /* number of new pivots */ len_t nr; /* number of rows set */ len_t nc; /* number of columns */ len_t nru; /* number of upper rows (in ABCD splicing) */ len_t nrl; /* number of lower rows (in ABCD splicing) */ len_t ncl; /* number of left columns (in ABCD splicing) */ len_t ncr; /* number of right columns (in ABCD splicing) */ len_t rbal; /* length of reducer binary array */ deg_t cd; /* current degree */ }; /* signature matrix stuff, stores information from previous and current step */ typedef struct smat_t smat_t; struct smat_t { hm_t **cr; /* current matrix rows, hashes resp. columns */ hm_t **pr; /* previous matrix rows, hashes resp. columns */ cf32_t **cc32; /* current matrix coefficients */ cf32_t **pc32; /* previous matrix coefficients */ deg_t cd; /* current degree */ len_t nlm; /* number of new leading monomials for basis from */ /* current matrix */ len_t csz; /* number of rows memory is allocated */ /* for in current matrix */ len_t cld; /* number of rows stored in current matrix */ len_t pld; /* number of rows stored in previous matrix */ len_t nc; /* number of columns in current matrix */ len_t nz; /* number of zero reductions during linear algebra */ /* on current matrix */ }; /* tracer stuff */ typedef struct primes_t primes_t; struct primes_t { uint32_t *p; /* array of primes */ len_t old; /* old load of array */ len_t ld; /* current load of array */ }; /* represents the trace data for one saturation step */ typedef struct ts_t ts_t; struct ts_t { len_t *rri; /* reducer rows information in the format * basis index1, multiplier1, * basis index2, multiplier2,... */ len_t *tri; /* to be reduced rows information in the format */ /* basis index1, multiplier1, * basis index2, multiplier2,... */ len_t lml; /* number of non-redundant elements in basis */ deg_t deg; /* minimal degree to start saturation process */ len_t f4rd; /* round of f4 */ hm_t *nlms; /* hashes of new leading monomials represented * in basis hash table */ len_t rld; /* load of reducer rows information*/ len_t tld; /* load of to be reduced rows information*/ len_t nlm; /* number of new leading monomials in this step */ }; typedef struct td_t td_t; struct td_t { len_t *rri; /* reducer rows information in the format */ /* basis index1, multiplier1, * basis index2, multiplier2,... */ len_t *tri; /* to be reduced rows information in the format */ /* basis index1, multiplier1, * basis index2, multiplier2,... */ hm_t *nlms; /* hashes of new leading monomials represented * in basis hash table */ rba_t **rba; /* reducer binary array for each to be reduced row */ deg_t deg; /* degree of elements in trace */ len_t rld; /* load of reducer rows information*/ len_t tld; /* load of to be reduced rows information*/ len_t nlm; /* number of new leading monomials in this step */ }; /* possible trace levels */ typedef enum {NO_TRACER, LEARN_TRACER, APPLY_TRACER} tl_t; typedef struct trace_t trace_t; struct trace_t { td_t *td; /* array of trace data for each round of F4 */ ts_t *ts; /* array of trace data for each saturation step */ len_t ltd; /* load of trace data td */ len_t lts; /* load of trace data ts */ len_t std; /* size allocated for trace data td */ len_t sts; /* size allocated for trace data ts */ sdm_t *lm; /* final minimal leading ideal represented as short divisor masks */ bl_t *lmps; /* minimal basis geneator positions */ hm_t *lmh; /* minimal basis leading monomial hashes represented in basis hash table */ bl_t lml; /* final number of lead monomials of non redundant elements in basis */ len_t *rd; /* rounds in which saturation steps lead to * non-trivial kernels */ len_t rld; /* load of rounds stored, i.e. how often do saturate */ len_t rsz; /* size of rounds stored */ }; /* meta data stuff */ typedef struct md_t md_t; struct md_t { /* trace data */ trace_t *tr; tl_t trace_level; int32_t trace_rd; /* hash table data */ ht_t *ht; len_t np; /* new pivots */ hi_t *hcm; ps_t *ps; double round_ctime; double select_ctime; double symbol_ctime; double la_ctime; double update_ctime; double convert_ctime; double f4_ctime; double reduce_gb_ctime; double tracer_ctime; double rht_ctime; double nf_ctime; double round_rtime; double select_rtime; double symbol_rtime; double la_rtime; double update_rtime; double convert_rtime; double f4_rtime; double reduce_gb_rtime; double tracer_rtime; double rht_rtime; double nf_rtime; int64_t num_pairsred; int64_t num_gb_crit; int64_t num_syz_crit; int64_t num_rew_crit; int64_t num_redundant_old; int64_t num_redundant; int64_t num_rht; int64_t num_rowsred; int64_t num_zerored; int64_t mat_max_nrows; int64_t mat_max_ncols; double mat_max_density; int32_t ngens_input; int32_t ngens_invalid; int32_t ngens; int32_t init_bs_sz; int32_t nvars; int32_t mnsel; int32_t homogeneous; uint32_t gfc; /* global field characteristic */ uint32_t fc; int32_t nev; /* number of elimination variables */ int32_t mo; /* monomial ordering: 0=DRL, 1=LEX*/ int32_t laopt; int32_t init_hts; int32_t nthrds; int32_t reset_ht; int32_t current_rd; int32_t current_deg; deg_t max_gb_degree; uint64_t max_bht_size; uint64_t max_sht_size; uint64_t max_uht_size; int64_t nterms_basis; int32_t size_basis; int32_t ff_bits; int32_t nf; int32_t f4_qq_round; int32_t use_signatures; /* module monomial ordering: 0 = off, 1=SCHREYER, 2=POT, 3=DPOT */ int32_t reduce_gb; int32_t in_final_reduction_step; deg_t min_deg_in_first_deg_fall; uint32_t prime_start; int32_t nprimes; int32_t info_level; int32_t gen_pbm_file; double trace_nr_mult; double trace_nr_add; uint64_t trace_nr_red; double application_nr_mult; double application_nr_add; uint64_t application_nr_red; int32_t print_gb; /* for f4sat */ uint32_t new_multipliers; uint32_t nr_kernel_elts; }; /* function pointers */ /* extern bs_t *(*initialize_basis)( * const int32_t ngens * ); */ extern void (*normalize_initial_basis)( bs_t *bs, const uint32_t fc ); extern int (*initial_input_cmp)( const void *a, const void *b, void *ht ); extern int (*initial_gens_cmp)( const void *a, const void *b, void *ht ); extern int (*monomial_cmp)( const hi_t a, const hi_t b, const ht_t *ht ); extern int (*spair_cmp)( const void *a, const void *b, void *htp ); extern int (*hcm_cmp)( const void *a, const void *b, void *htp ); /* linear algebra routines */ extern void (*sba_linear_algebra)( smat_t *smat, crit_t *syz, md_t *st, const ht_t * const ht ); extern void (*exact_linear_algebra)( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ); extern void (*linear_algebra)( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ); extern int (*application_linear_algebra)( mat_t *mat, const bs_t * const bs, md_t *st ); extern void (*trace_linear_algebra)( trace_t *trace, mat_t *mat, const bs_t * const bs, md_t *st ); extern void (* interreduce_matrix_rows)( mat_t *mat, bs_t *bs, md_t *st, int free_basis ); extern cf32_t *(*reduce_dense_row_by_old_pivots_ff_32)( int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t * const * const pivs, const hi_t dpiv, const uint32_t fc ); extern hm_t *(*sba_reduce_dense_row_by_known_pivots_sparse_ff_32)( int64_t *dr, smat_t *smat, hm_t *const *pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const hm_t sm, /* signature monomial of row reduced */ const len_t si, /* signature index of row reduced */ const len_t ri, /* index of row in matrix */ md_t *st ); extern hm_t *(*reduce_dense_row_by_known_pivots_sparse_ff_32)( int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t *const *pivs, const hi_t dpiv, const hm_t tmp_pos, const len_t mh, /* multiplier hash for tracing */ const len_t bi, /* basis index of generating element */ const len_t tr, /* trace data? */ md_t *st ); extern hm_t *(*trace_reduce_dense_row_by_known_pivots_sparse_ff_32)( rba_t *rba, int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t *const *pivs, const hi_t dpiv, const hm_t tmp_pos, const len_t mh, const len_t bi, md_t *st ); extern cf32_t *(*reduce_dense_row_by_all_pivots_ff_32)( int64_t *dr, mat_t *mat, const bs_t * const bs, len_t *pc, hm_t *const *pivs, cf32_t *const *dpivs, const uint32_t fc ); extern cf32_t *(*reduce_dense_row_by_dense_new_pivots_ff_32)( int64_t *dr, len_t *pc, cf32_t * const * const pivs, const len_t ncr, const uint32_t fc ); #endif msolve-0.6.5/src/neogb/engine.c000066400000000000000000000120221456710632100163230ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "engine.h" int initialize_gba_input_data( bs_t **bsp, ht_t **bhtp, md_t **stp, /* input values */ const int32_t *lens, const int32_t *exps, const void *cfs, uint32_t field_char, int32_t mon_order, int32_t elim_block_len, int32_t nr_vars, int32_t nr_gens, int32_t nr_nf, int32_t ht_size, int32_t nr_threads, int32_t max_nr_pairs, int32_t reset_ht, int32_t la_option, int32_t use_signatures, int32_t reduce_gb, int32_t pbm_file, int32_t info_level ) { bs_t *bs = *bsp; md_t *st = *stp; /* initialize stuff */ st = allocate_meta_data(); int *invalid_gens = NULL; int res = validate_input_data(&invalid_gens, cfs, lens, &field_char, &mon_order, &elim_block_len, &nr_vars, &nr_gens, &nr_nf, &ht_size, &nr_threads, &max_nr_pairs, &reset_ht, &la_option, &use_signatures, &reduce_gb, &info_level); /* all data is corrupt */ if (res == -1) { free(invalid_gens); return res; } /* checks and set all meta data. if a nonzero value is returned then * some of the input data is corrupted. */ if (check_and_set_meta_data(st, lens, exps, cfs, invalid_gens, field_char, mon_order, elim_block_len, nr_vars, nr_gens, nr_nf, ht_size, nr_threads, max_nr_pairs, reset_ht, la_option, use_signatures, reduce_gb, pbm_file, info_level)) { return 0; } /* initialize basis */ bs = initialize_basis(st); ht_t *bht = bs->ht; import_input_data(bs, st, 0, st->ngens_input, lens, exps, cfs, invalid_gens); print_initial_statistics(stderr, st); /* for faster divisibility checks, needs to be done after we have * read some input data for applying heuristics */ calculate_divmask(bht); /* sort initial elements, smallest lead term first */ sort_r(bs->hm, (unsigned long)bs->ld, sizeof(hm_t *), initial_input_cmp, bht); /* normalize input generators */ if (st->fc > 0) { normalize_initial_basis(bs, st->fc); } else { if (st->fc == 0) { remove_content_of_initial_basis(bs); } } *bsp = bs; *bhtp = bht; *stp = st; free(invalid_gens); return 1; } bs_t *core_gba( bs_t *bs, md_t *md, int32_t *errp, const len_t fc ) { return core_f4(bs, md, errp, fc); } int64_t export_results_from_gba( /* return values */ int32_t *bld, /* basis load */ int32_t **blen, /* length of each poly in basis */ int32_t **bexp, /* basis exponent vectors */ void **bcf, /* coefficients of basis elements */ void *(*mallocp) (size_t), bs_t **bsp, ht_t **bhtp, md_t **stp ) { if ((*stp)->use_signatures == 0) { return export_results_from_f4(bld, blen, bexp, bcf, mallocp, bsp, bhtp, stp); } else { exit(1); } } bs_t *gba_trace_learning_phase( trace_t *trace, /* trace of the GB Algorithm */ ht_t * tht, /* trace hash table for multipliers */ const bs_t * const ggb, /* global basis */ ht_t *gbht, /* global basis hash table, generated * in this run, used in upcoming runs */ md_t *gst, /* global statistics */ const int32_t fc /* characteristic of field */ ) { if (gst->use_signatures == 0) { return f4_trace_learning_phase(trace, tht, ggb, gbht, gst, fc); } else { exit(1); } } bs_t *gba_trace_application_phase( trace_t *trace, /* trace of the GB Algorithm */ ht_t * tht, /* trace hash table for multipliers */ const bs_t * const ggb, /* global basis */ ht_t *lbht, /* global basis hash table, generated * in this run, used in upcoming runs */ md_t *gst, /* global statistics */ const int32_t fc /* characteristic of field */ ) { if (gst->use_signatures == 0) { return f4_trace_application_phase(trace, tht, ggb, lbht, gst, fc); } else { exit(1); } } msolve-0.6.5/src/neogb/engine.h000066400000000000000000000055201456710632100163350ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef GB_ENGINE_H #define GB_ENGINE_H #include "data.h" int initialize_gba_input_data( bs_t **bsp, ht_t **bhtp, md_t **stp, /* input values */ const int32_t *lens, const int32_t *exps, const void *cfs, uint32_t field_char, int32_t mon_order, int32_t elim_block_len, int32_t nr_vars, int32_t nr_gens, int32_t nr_nf, int32_t ht_size, int32_t nr_threads, int32_t max_nr_pairs, int32_t reset_ht, int32_t la_option, int32_t use_signatures, int32_t reduce_gb, int32_t pbm_file, int32_t info_level ); bs_t *core_gba( bs_t *bs, md_t *md, int32_t *errp, const len_t fc ); int64_t export_results_from_gba( /* return values */ int32_t *bld, /* basis load */ int32_t **blen, /* length of each poly in basis */ int32_t **bexp, /* basis exponent vectors */ void **bcf, /* coefficients of basis elements */ void *(*mallocp) (size_t), bs_t **bsp, ht_t **bhtp, md_t **stp ); bs_t *gba_trace_learning_phase( trace_t *trace, /* trace of the GB Algorithm */ ht_t * tht, /* trace hash table for multipliers */ const bs_t * const ggb, /* global basis */ ht_t *gbht, /* global basis hash table, generated * in this run, used in upcoming runs */ md_t *gst, /* global statistics */ const int32_t fc /* characteristic of field */ ); bs_t *gba_trace_application_phase( trace_t *trace, /* trace of the GB Algorithm */ ht_t * tht, /* trace hash table for multipliers */ const bs_t * const ggb, /* global basis */ ht_t *lbht, /* global basis hash table, generated * in this run, used in upcoming runs */ md_t *gst, /* global statistics */ const int32_t fc /* characteristic of field */ ); #endif msolve-0.6.5/src/neogb/f4.c000066400000000000000000000557401456710632100154050ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "f4.h" void static final_remove_redundant_elements( bs_t *bs, md_t *md, const ht_t * const ht ) { len_t i, j; for (i = 0; i < bs->lml; ++i) { hm_t nch = bs->hm[bs->lmps[i]][OFFSET]; for (j = 0; j < i; ++j) { if (bs->red[bs->lmps[j]] == 0 && check_monomial_division(nch, bs->hm[bs->lmps[j]][OFFSET], ht) ) { bs->red[bs->lmps[i]] = 1; md->num_redundant++; break; } } for (j = i+1; j < bs->lml; ++j) { if (bs->red[bs->lmps[j]] == 0 && check_monomial_division(nch, bs->hm[bs->lmps[j]][OFFSET], ht) ) { bs->red[bs->lmps[i]] = 1; md->num_redundant++; break; } } } j = 0; for (i = 0; i < bs->lml; ++i) { if (bs->red[bs->lmps[i]] == 0) { bs->lm[j] = bs->lm[i]; bs->lmps[j] = bs->lmps[i]; ++j; } } bs->lml = j; } /* The parameters themselves are handled by julia, thus we only * free what they are pointing to, julia's garbage collector then * takes care of everything leftover. */ void free_f4_julia_result_data( void (*freep) (void *), int32_t **blen, /* length of each poly in basis */ int32_t **bexp, /* basis exponent vectors */ void **bcf, /* coefficients of basis elements */ const int64_t ngens, const int64_t field_char ) { /* lengths resp. nterms */ int32_t *lens = *blen; /* int64_t i; * int64_t len = 0; * for (i = 0; i < ngens; ++i) { * len += (int64_t)lens[i]; * } */ (*freep)(lens); lens = NULL; *blen = lens; /* exponent vectors */ int32_t *exps = *bexp; (*freep)(exps); exps = NULL; *bexp = exps; /* coefficients */ if (field_char == 0) { /* mpz_t **cfs = (mpz_t **)bcf; * for (i = 0; i < len; ++i) { * mpz_clear((*cfs)[i]); * } * (*freep)(*cfs); * *cfs = NULL; */ } else { if (field_char > 0) { int32_t *cfs = *((int32_t **)bcf); (*freep)(cfs); cfs = NULL; } } *bcf = NULL; } static void clear_matrix( mat_t *mat ) { len_t i; for (i = 0; i < mat->rbal; ++i) { free(mat->rba[i]); } free(mat->rba); mat->rba = NULL; free(mat->rr); mat->rr = NULL; free(mat->tr); mat->tr = NULL; free(mat->cf_8); mat->cf_8 = NULL; free(mat->cf_16); mat->cf_16 = NULL; free(mat->cf_32); mat->cf_32 = NULL; free(mat->cf_qq); mat->cf_qq = NULL; free(mat->cf_ab_qq); mat->cf_ab_qq = NULL; } #if 0 static void intermediate_reduce_basis( bs_t *bs, mat_t *mat, hi_t **hcmp, ht_t **bhtp, ht_t **shtp, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); len_t i, j; ht_t *bht = *bhtp; ht_t *sht = *shtp; hi_t *hcm = *hcmp; exp_t etmp[bht->evl]; memset(etmp, 0, (unsigned long)(bht->evl) * sizeof(exp_t)); mat->rr = (hm_t **)malloc((unsigned long)bs->lml * 2 * sizeof(hm_t *)); mat->nr = 0; mat->sz = 2 * bs->lml; /* add all non-redundant basis elements as matrix rows */ for (i = 0; i < bs->lml; ++i) { mat->rr[mat->nr] = multiplied_poly_to_matrix_row( sht, bht, 0, etmp, bs->hm[bs->lmps[i]]); sht->hd[mat->rr[mat->nr][OFFSET]].idx = 1; mat->nr++; } mat->nc = mat->nr; /* needed for correct counting in symbol */ symbolic_preprocessing(mat, bs, st, sht, bht); /* no known pivots, we need mat->ncl = 0, so set all indices to 1 */ for (i = 0; i < sht->eld; ++i) { sht->hd[i].idx = 1; } /* generate hash <-> column mapping */ if (st->info_level > 1) { printf("reduce intermediate basis "); fflush(stdout); } convert_hashes_to_columns(mat, st, sht); mat->nc = mat->ncl + mat->ncr; /* sort rows */ sort_matrix_rows_decreasing(mat->rr, mat->nru); /* do the linear algebra reduction, do NOT free basis data */ interreduce_matrix_rows(mat, bs, st, 0); /* remap rows to basis elements (keeping their position in bs) */ convert_sparse_matrix_rows_to_basis_elements(mat, bs, bht, sht, st); clear_matrix(mat); clean_hash_table(sht); /* printf("bs->lml %u | bs->ld %u | mat->np %u\n", bs->lml, bs->ld, mat->np); */ /* we may have added some multiples of reduced basis polynomials * from the matrix, so we get rid of them. */ i = 0; for (i = 0; i < bs->ld; ++i) { for (j = 0; j < mat->np; ++j) { if (bs->hm[i][OFFSET] == bs->hm[bs->ld+j][OFFSET]) { free(bs->hm[i]); bs->hm[i] = bs->hm[bs->ld+j]; bs->hm[i][COEFFS] = i; switch(st->ff_bits) { case 8: free(bs->cf_8[i]); bs->cf_8[i] = bs->cf_8[bs->ld+j]; break; case 16: free(bs->cf_16[i]); bs->cf_16[i] = bs->cf_16[bs->ld+j]; break; case 32: free(bs->cf_32[i]); bs->cf_32[i] = bs->cf_32[bs->ld+j]; break; } } } } for (i = bs->ld; i < bs->ld+mat->np; ++i) { bs->hm[i] = NULL; switch(st->ff_bits) { case 8: bs->cf_8[i] = NULL; break; case 16: bs->cf_16[i] = NULL; break; case 32: bs->cf_32[i] = NULL; break; } } *hcmp = hcm; /* timings */ ct1 = cputime(); rt1 = realtime(); st->reduce_gb_ctime = ct1 - ct0; st->reduce_gb_rtime = rt1 - rt0; if (st->info_level > 1) { printf("%13.2f sec\n", rt1-rt0); } if (st->info_level > 1) { printf("-------------------------------------------------\ ----------------------------------------\n"); } } #endif static void reduce_basis( bs_t *bs, mat_t *mat, md_t *md ) { /* timings */ double ct, rt; ct = cputime(); rt = realtime(); len_t i, j, k; ht_t *bht = bs->ht; ht_t *sht = md->ht; exp_t etmp[bht->evl]; memset(etmp, 0, (unsigned long)(bht->evl) * sizeof(exp_t)); md->in_final_reduction_step = 1; mat->rr = (hm_t **)malloc((unsigned long)bs->lml * 2 * sizeof(hm_t *)); mat->nr = 0; mat->sz = 2 * bs->lml; /* add all non-redundant basis elements as matrix rows */ for (i = 0; i < bs->lml; ++i) { mat->rr[mat->nr] = multiplied_poly_to_matrix_row( sht, bht, 0, etmp, bs->hm[bs->lmps[i]]); sht->hd[mat->rr[mat->nr][OFFSET]].idx = 1; mat->nr++; } mat->nc = mat->nr; /* needed for correct counting in symbol */ symbolic_preprocessing(mat, bs, md); /* no known pivots, we need mat->ncl = 0, so set all indices to 1 */ for (i = 0; i < sht->eld; ++i) { sht->hd[i].idx = 1; } /* generate hash <-> column mapping */ if (md->info_level > 1) { printf("reduce final basis "); fflush(stdout); } convert_hashes_to_columns(mat, md, sht); mat->nc = mat->ncl + mat->ncr; /* sort rows */ sort_matrix_rows_decreasing(mat->rr, mat->nru); /* do the linear algebra reduction and free basis data afterwards */ interreduce_matrix_rows(mat, bs, md, 1); convert_sparse_matrix_rows_to_basis_elements( 1, mat, bs, bht, sht, md); /* set sht = NULL, otherwise we might run in a double-free * of sht and bht at the end */ /* sht = NULL; md->ht = sht; */ bs->ld = mat->np; /* clean_hash_table(sht); */ clear_matrix(mat); /* we may have added some multiples of reduced basis polynomials * from the matrix, so we get rid of them. */ k = 0; i = 0; start: for (; i < bs->ld; ++i) { for (j = 0; j < k; ++j) { if (check_monomial_division( bs->hm[bs->ld-1-i][OFFSET], bs->hm[bs->lmps[j]][OFFSET], bht)) { ++i; goto start; } } bs->lmps[k] = bs->ld-1-i; bs->lm[k++] = bht->hd[bs->hm[bs->ld-1-i][OFFSET]].sdm; } bs->lml = k; md->in_final_reduction_step = 0; print_round_timings(stdout, md, rt, ct); print_round_information_footer(stdout, md); } static int32_t initialize_f4( bs_t **lbsp, md_t **lmdp, mat_t **matp, md_t *gmd, bs_t *gbs, len_t fc ) { bs_t *bs = *lbsp; mat_t *mat = *matp; int32_t done = 0; md_t *md = *lmdp; md = copy_meta_data(gmd, fc); md->fc = fc; md->hcm = (hi_t *)malloc(sizeof(hi_t)); if (gmd->fc != fc) { reset_function_pointers(fc, md->laopt); bs = copy_basis_mod_p(gbs, md); if (md->laopt < 40) { if (md->trace_level != APPLY_TRACER) { md->trace_level = LEARN_TRACER; } } } else { bs = gbs; md->trace_level = NO_TRACER; } normalize_initial_basis(bs, fc); md->ht = initialize_secondary_hash_table(bs->ht, md); /* matrix holding sparse information generated during symbolic preprocessing */ mat = (mat_t *)calloc(1, sizeof(mat_t)); if (md->trace_level != APPLY_TRACER) { /* pair set */ md->ps = initialize_pairset(); /* reset bs->ld for first update process */ bs->ld = 0; } else { bs->ld = md->ngens; } /* TODO: make this a command line argument */ md->max_gb_degree = INT32_MAX; /* link tracer into basis */ if (md->trace_level == LEARN_TRACER) { md->tr = initialize_trace(bs, md); md->min_deg_in_first_deg_fall = INT32_MAX; } /* move input generators to basis and generate first spairs. always check redundancy since input generators may be redundant even so they are homogeneous. */ if (md->trace_level != APPLY_TRACER) { md->np = md->ngens; done = update(bs, md); } *lbsp = bs; *matp = mat; *lmdp = md; return done; } static int32_t compute_new_elements( mat_t *mat, bs_t *bs, md_t *md, int32_t *errp ) { len_t i; ht_t *ht = bs->ht; ht_t *sht = md->ht; convert_hashes_to_columns(mat, md, sht); sort_matrix_rows_decreasing(mat->rr, mat->nru); linear_algebra(mat, bs, bs, md); /* check for bad prime */ if (md->trace_level == APPLY_TRACER) { if (mat->np != md->tr->td[md->trace_rd].nlm) { if (md->info_level > 0) { fprintf(stderr, "Wrong number of new elements, bad prime."); } *errp = 1; return 1; } } /* columns indices are mapped back to exponent hashes */ if (mat->np > 0) { convert_sparse_matrix_rows_to_basis_elements( -1, mat, bs, ht, sht, md); } clean_hash_table(sht); /* all rows in mat are now polynomials in the basis, * so we do not need the rows anymore */ clear_matrix(mat); /* check for bad prime */ if (md->trace_level == APPLY_TRACER) { for (i = 0; i < md->np; ++i) { if (bs->hm[bs->ld+i][OFFSET] != md->tr->td[md->trace_rd].nlms[i]) { if (md->info_level > 0) { fprintf(stderr, "Wrong leading term for new element %u/%u, bad prime.", i, mat->np); } *errp = 2; return 1; } } } if (md->trace_level == LEARN_TRACER && md->np > 0) { add_lms_to_trace(md->tr, bs, md->np); md->tr->ltd++; } if (md->trace_level == APPLY_TRACER) { bs->ld += md->np; md->trace_rd++; if (md->trace_rd >= md->tr->ltd) { return 1; } } return 0; } static void process_redundant_elements( bs_t *bs, md_t *md ) { len_t i, j; ht_t *ht = bs->ht; if (md->trace_level != APPLY_TRACER) { for (i = 0; i < bs->lml; ++i) { hm_t nch = bs->hm[bs->lmps[i]][OFFSET]; for (j = 0; j < i; ++j) { if (bs->red[bs->lmps[j]] == 0 && check_monomial_division(nch, bs->hm[bs->lmps[j]][OFFSET], ht) ) { bs->red[bs->lmps[i]] = 1; md->num_redundant++; break; } } for (j = i+1; j < bs->lml; ++j) { if (bs->red[bs->lmps[j]] == 0 && check_monomial_division(nch, bs->hm[bs->lmps[j]][OFFSET], ht) ) { bs->red[bs->lmps[i]] = 1; md->num_redundant++; break; } } } j = 0; for (i = 0; i < bs->lml; ++i) { if (bs->red[bs->lmps[i]] == 0) { bs->lm[j] = bs->lm[i]; bs->lmps[j] = bs->lmps[i]; ++j; } } bs->lml = j; /* At the moment we do not directly remove the eliminated polynomials from * the resulting basis. */ #if 0 if (md->nev > 0) { j = 0; for (i = 0; i < bs->lml; ++i) { if (ht->ev[bs->hm[bs->lmps[i]][OFFSET]][0] == 0) { bs->lm[j] = bs->lm[i]; bs->lmps[j] = bs->lmps[i]; ++j; } } bs->lml = j; } #endif } if (md->trace_level == APPLY_TRACER) { /* apply non-redundant basis data from trace to basis * before interreduction */ bs->lml = md->tr->lml; free(bs->lmps); bs->lmps = (bl_t *)calloc((unsigned long)bs->lml, sizeof(bl_t)); memcpy(bs->lmps, md->tr->lmps, (unsigned long)bs->lml * sizeof(bl_t)); free(bs->lm); bs->lm = (sdm_t *)calloc((unsigned long)bs->lml, sizeof(sdm_t)); memcpy(bs->lm, md->tr->lm, (unsigned long)bs->lml * sizeof(sdm_t)); } if (md->trace_level == LEARN_TRACER) { /* store information in trace */ md->tr->lml = bs->lml; md->tr->lmps = (bl_t *)calloc((unsigned long)md->tr->lml, sizeof(bl_t)); memcpy(md->tr->lmps, bs->lmps, (unsigned long)md->tr->lml * sizeof(bl_t)); md->tr->lm = (sdm_t *)calloc((unsigned long)md->tr->lml, sizeof(sdm_t)); memcpy(md->tr->lm, bs->lm, (unsigned long)md->tr->lml * sizeof(sdm_t)); /* do not track the final reduction step */ } } static void reduce_final_basis( bs_t *bs, mat_t *mat, md_t *md ) { if (md->reduce_gb) { md->in_final_reduction_step = 1; /* timings */ double ct, rt; ct = cputime(); rt = realtime(); len_t i; ht_t *bht = bs->ht; ht_t *sht = md->ht; /* add all non-redundant basis elements as matrix rows */ mat->tr = (hm_t **)malloc((unsigned long)bs->lml * sizeof(hm_t *)); for (i = 0; i < bs->lml; ++i) { mat->tr[i] = poly_to_matrix_row( sht, bht, bs->hm[bs->lmps[i]]); sht->hd[mat->tr[i][OFFSET]].idx = 1; } mat->nr = mat->nrl = mat->sz = bs->lml; mat->nc = 0; symbolic_preprocessing(mat, bs, md); /* no known pivots, we need mat->ncl = 0, so set all indices to 1 */ for (i = 0; i < sht->eld; ++i) { sht->hd[i].idx = 1; } /* generate hash <-> column mapping */ if (md->info_level > 1) { printf("reduce final basis "); fflush(stdout); } convert_hashes_to_columns(mat, md, sht); mat->nc = mat->ncl + mat->ncr; sort_matrix_rows_decreasing(mat->rr, mat->nru); sort_matrix_rows_increasing(mat->tr, mat->nrl); exact_linear_algebra(mat, bs, bs, md); free_basis_elements(bs); convert_sparse_matrix_rows_to_basis_elements( 0, mat, bs, bht, sht, md); bs->ld = bs->lml = mat->np; clear_matrix(mat); for (i = 0; i < bs->ld; ++i) { bs->lmps[i] = i; bs->lm[i] = bht->hd[bs->hm[i][OFFSET]].sdm; } md->in_final_reduction_step = 0; /* timings */ print_round_timings(stdout, md, rt, ct); print_round_information_footer(stdout, md); } } static void free_local_data( mat_t **matp, md_t **mdp ) { free_meta_data(mdp); free(*matp); *matp = NULL; } static void finalize_f4( md_t *gmd, bs_t *gbs, bs_t **bsp, md_t **lmdp, mat_t **matp, int32_t err ) { if (err > 0) { free_basis_and_only_local_hash_table_data(bsp); } if ((*lmdp)->trace_level == LEARN_TRACER) { gmd->tr = (*lmdp)->tr; gmd->trace_level = APPLY_TRACER; } gmd->min_deg_in_first_deg_fall = (*lmdp)->min_deg_in_first_deg_fall; free_local_data(matp, lmdp); } bs_t *core_f4( bs_t *gbs, md_t *gmd, int32_t *errp, const len_t fc ) { double ct = cputime(); double rt = realtime(); bs_t *bs = NULL; md_t *md = NULL; mat_t *mat = NULL; /* marker for end of computation */ int32_t done = 0; /* timings for one round */ double rrt, crt; done = initialize_f4(&bs, &md, &mat, gmd, gbs, fc); /* let's start the f4 rounds, we are done when no more spairs are left in the pairset or if we found a constant in the basis. */ print_round_information_header(stdout, md); /* reset error */ *errp = 0; while (!done) { rrt = realtime(); crt = cputime(); md->max_bht_size = md->max_bht_size > bs->ht->esz ? md->max_bht_size : bs->ht->esz; done = preprocessing(mat, bs, md); if (!done) { done = compute_new_elements(mat, bs, md, errp); } if (!done && md->trace_level != APPLY_TRACER) { done = update(bs, md); } print_round_timings(stdout, md, rrt, crt); } if (*errp > 0) { free_basis_and_only_local_hash_table_data(&bs); } else { print_round_information_footer(stdout, md); /* remove possible redudant elements */ process_redundant_elements(bs, md); /* reduce final basis? */ reduce_final_basis(bs, mat, md); md->f4_rtime = realtime() - rt; md->f4_ctime = cputime() - ct; get_and_print_final_statistics(stdout, md, bs); finalize_f4(gmd, gbs, &bs, &md, &mat, *errp); } return bs; } int64_t export_results_from_f4( /* return values */ int32_t *bld, /* basis load */ int32_t **blen, /* length of each poly in basis */ int32_t **bexp, /* basis exponent vectors */ void **bcf, /* coefficients of basis elements */ void *(*mallocp) (size_t), bs_t **bsp, ht_t **bhtp, md_t **stp ) { bs_t *bs = *bsp; ht_t *bht = *bhtp; md_t *st = *stp; st->nterms_basis = export_data( bld, blen, bexp, bcf, mallocp, bs, bht, st); st->size_basis = *bld; return st->nterms_basis; } /* we get from julia the generators as three arrays: * 0. a pointer to an int32_t array for returning the basis to julia * 1. an array of the lengths of each generator * 2. an array of all coefficients of all generators in the order: * first all coefficients of generator 1, then all of generator 2, ... * 3. an array of all exponents of all generators in the order: * first all exponents of generator 1, then all of generator 2, ... * * RETURNs the length of the jl_basis array */ int64_t export_f4( void *(*mallocp) (size_t), /* return values */ int32_t *bld, /* basis load */ int32_t **blen, /* length of each poly in basis */ int32_t **bexp, /* basis exponent vectors */ void **bcf, /* coefficients of basis elements */ /* input values */ const int32_t *lens, const int32_t *exps, const void *cfs, const uint32_t field_char, const int32_t mon_order, const int32_t elim_block_len, const int32_t nr_vars, const int32_t nr_gens, const int32_t ht_size, const int32_t nr_threads, const int32_t max_nr_pairs, const int32_t reset_ht, const int32_t la_option, const int32_t reduce_gb, const int32_t pbm_file, const int32_t info_level ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* data structures for basis, hash table and statistics */ bs_t *bs = NULL; ht_t *bht = NULL; md_t *md = NULL; int success = 0; const int32_t use_signatures = 0; success = initialize_gba_input_data(&bs, &bht, &md, lens, exps, cfs, field_char, mon_order, elim_block_len, nr_vars, nr_gens, 0 /* # normal forms */, ht_size, nr_threads, max_nr_pairs, reset_ht, la_option, use_signatures, reduce_gb, pbm_file, info_level); /* all input generators are invalid */ if (success == -1) { return_zero(bld, blen, bexp, bcf, nr_vars, field_char, mallocp); return 1; } if (success == 0) { printf("Bad input data, stopped computation.\n"); exit(1); } int err = 0; bs = core_f4(bs, md, &err, field_char); if (err) { printf("Problem with F4, stopped computation.\n"); exit(1); } int64_t nterms = export_results_from_f4(bld, blen, bexp, bcf, mallocp, &bs, &bht, &md); /* timings */ ct1 = cputime(); rt1 = realtime(); md->f4_ctime = ct1 - ct0; md->f4_rtime = rt1 - rt0; get_and_print_final_statistics(stderr, md, bs); /* free and clean up */ free_shared_hash_data(bht); if (bs != NULL) { free_basis(&bs); } free(md); md = NULL; return nterms; } msolve-0.6.5/src/neogb/f4.h000066400000000000000000000051461456710632100154050ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef GB_F4_H #define GB_F4_H #include "data.h" void free_f4_julia_result_data( void (*freep) (void *), int32_t **blen, /* length of each poly in basis */ int32_t **bexp, /* basis exponent vectors */ void **bcf, /* coefficients of basis elements */ const int64_t ngens, const int64_t field_char ); int64_t export_f4( void *(*mallocp) (size_t), int32_t *bld, /* basis load */ int32_t **blen, /* length of each poly in basis */ int32_t **bexp, /* basis exponent vectors */ void **bcf, /* coefficients of basis elements */ const int32_t *lens, const int32_t *exps, const void *cfs, const uint32_t field_char, const int32_t mon_order, const int32_t elim_block_len, const int32_t nr_vars, const int32_t nr_gens, const int32_t ht_size, const int32_t nr_threads, const int32_t max_nr_pairs, const int32_t reset_hash_table, const int32_t la_option, const int32_t reduce_gb, const int32_t pbm_file, const int32_t info_level ); int64_t export_results_from_f4( /* return values */ int32_t *bld, /* basis load */ int32_t **blen, /* length of each poly in basis */ int32_t **bexp, /* basis exponent vectors */ void **bcf, /* coefficients of basis elements */ void *(*mallocp) (size_t), bs_t **bsp, ht_t **bhtp, md_t **stp ); bs_t *core_f4( bs_t *gbs, md_t *gmd, int32_t *errp, const len_t fc ); bs_t *modular_f4( const bs_t * const ggb, /* global basis */ ht_t * gbht, /* global basis hash table, shared */ md_t *gst, /* global statistics */ const uint32_t fc /* characteristic of field */ ); #endif msolve-0.6.5/src/neogb/f4sat.c000066400000000000000000000574501456710632100161150ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "f4sat.h" static inline void free_kernel_coefficients( bs_t *kernel ) { len_t i; for (i = 0; i < kernel->ld; ++i) { free(kernel->cf_32[i]); } } static inline int is_pure_power( const exp_t * const ev, const ht_t * const ht ) { len_t i; len_t ctr = 0; const len_t ebl = ht->ebl; const len_t evl = ht->evl; const len_t nv = ht->nv; for (i = 1; i < ebl; ++i) { if (ev[i] == 0) { ctr++; } } for (i = ebl+1; i < evl; ++i) { if (ev[i] == 0) { ctr++; } } if (ctr == nv-1) { return 1; } return 0; } static inline int is_zero_dimensional( const bs_t * const bs, const ht_t * const ht ) { len_t i; len_t ctr = 0; const len_t nv = ht->nv; const len_t lml = bs->lml; for (i = 0; i < lml; ++i) { if (is_pure_power(ht->ev[bs->hm[bs->lmps[i]][OFFSET]], ht)) { ctr ++; } } if (ctr == nv) { return 1; } return 0; } static int is_already_saturated( bs_t *bs, const bs_t * const sat, mat_t *mat, ht_t **bhtp, ht_t **shtp, md_t *st ) { printf("testing if system is already saturated: "); double rrt0, rrt1; rrt0 = realtime(); len_t i; /* hi_t *hcm = *hcmp; */ ht_t *bht = *bhtp; ht_t *sht = *shtp; /* add phi to basis and generate pairs with phi */ check_enlarge_basis(bs, 1, st); int is_constant = 0; /* copy old data from bs to restore after test */ const bl_t bld = bs->ld; const bl_t blo = bs->lo; const bl_t bsc = bs->constant; const len_t lml = bs->lml; sdm_t *lm = (sdm_t *)malloc((unsigned long)lml * sizeof(sdm_t)); memcpy(lm, bs->lm, (unsigned long)lml * sizeof(sdm_t)); bl_t *lmps = (bl_t *)malloc((unsigned long)lml * sizeof(bl_t)); memcpy(lmps, bs->lmps, (unsigned long)lml * sizeof(bl_t)); int8_t *red = (int8_t *)malloc((unsigned long)bs->sz * sizeof(int8_t)); memcpy(red, bs->red, (unsigned long)bs->sz * sizeof(int8_t)); ps_t *ps = initialize_pairset(); cf32_t *cf = (cf32_t *)malloc( (unsigned long)sat->hm[0][LENGTH] * sizeof(cf32_t)); memcpy(cf, sat->cf_32[sat->hm[0][COEFFS]], (unsigned long)sat->hm[0][LENGTH] * sizeof(cf32_t)); hm_t *hm = (hm_t *)malloc( (unsigned long)(sat->hm[0][LENGTH]+OFFSET) * sizeof(hm_t)); memcpy(hm, sat->hm[0], (unsigned long)(sat->hm[0][LENGTH]+OFFSET) * sizeof(hm_t)); bs->cf_32[bs->ld] = cf; hm[COEFFS] = bs->ld; bs->hm[bs->ld] = hm; update_basis_f4(ps, bs, bht, st, 1); /* suppress infolevel printing in the test step */ int32_t infolevel = st->info_level; st->info_level = 0; while (ps->ld > 0) { select_spairs_by_minimal_degree(mat, bs, st); /* select_all_spairs(mat, bs, ps, st, sht, bht, NULL); */ symbolic_preprocessing(mat, bs, st); convert_hashes_to_columns(mat, st, sht); sort_matrix_rows_decreasing(mat->rr, mat->nru); sort_matrix_rows_increasing(mat->tr, mat->nrl); /* linear algebra, depending on choice, see set_function_pointers() */ probabilistic_sparse_linear_algebra_ff_32(mat, bs, bs, st); /* columns indices are mapped back to exponent hashes */ if (mat->np > 0) { convert_sparse_matrix_rows_to_basis_elements( -1, mat, bs, bht, sht, st); } /* all rows in mat are now polynomials in the basis, * so we do not need the rows anymore */ clear_matrix(mat); // does not reset mat->np clean_hash_table(sht); update_basis_f4(ps, bs, bht, st, mat->np); /* if we found a constant we are done, so remove all remaining pairs */ if (bs->constant == 1) { ps->ld = 0; break; } } is_constant = bs->constant; /* reset basis data to state before starting test */ for (i = bld; i < bs->ld; ++i) { free(bs->cf_32[bs->hm[i][COEFFS]]); bs->cf_32[bs->hm[i][COEFFS]] = NULL; free(bs->hm[i]); bs->hm[i] = NULL; } if (ps != NULL) { free_pairset(&ps); } bs->ld = bld; bs->lo = blo; bs->constant = bsc; /* reset infolevel */ st->info_level = infolevel; free(bs->lm); bs->lm = lm; free(bs->lmps); bs->lmps = lmps; bs->lml = lml; free(bs->red); bs->red = red; /* *hcmp = hcm; */ *bhtp = bht; *shtp = sht; if (is_constant == 1) { printf("yes."); } else { printf("no."); } rrt1 = realtime(); if (st->info_level > 1) { printf("%40.2f sec\n", rrt1-rrt0); } return is_constant; } static inline unsigned long sum( const len_t * const ind, const len_t len) { len_t i; unsigned long sum = 0; for (i = 0; i < len; i++){ sum += ind[i]; } return sum; } static inline len_t generate_new_basis_elements( ht_t **htp, hm_t *cqb, const hm_t * const oqb, const len_t oqb_dim, const len_t * const ind, const bs_t * const bs ) { len_t i, j; ht_t *ht = *htp; const len_t nv = ht->nv; len_t ctr = 0; exp_t *etmp = calloc((unsigned long)(nv+1), sizeof(exp_t)); for (i = nv; i > 0; --i) { while (ht->esz - ht->eld < oqb_dim-ind[nv-i]) { enlarge_hash_table(ht); } for (j = ind[nv-i]; j < oqb_dim; ++j) { memcpy(etmp, ht->ev[oqb[j]], (unsigned long)(nv+1)*sizeof(exp_t));; etmp[i]++; etmp[DEG]++; cqb[ctr] = check_lm_divisibility_and_insert_in_hash_table( etmp, ht, bs ); if (cqb[ctr] != 0) { ctr++; } } } *htp = ht; free(etmp); return ctr; } static inline void update_indices( len_t *ind, const hm_t * const qb, const len_t oqb_dim, const len_t cqb_dim, const ht_t * const ht ) { len_t i, j, k; const len_t nv = ht->nv; const len_t dim = oqb_dim + cqb_dim; ind[0] = oqb_dim; for (i = nv-1; i > 0; --i) { for (j = ind[nv-1-i]; j < dim; ++j) { if (ht->ev[qb[j]][i+1] == 0) { ind[nv-i] = j; break; } for (k = i; k > 0; --k) { ind[nv-k] = dim; } } } } static len_t quotient_basis( hm_t **qbp, ht_t **htp, const bs_t * const bs, const deg_t max_deg ) { if (bs->constant == 1) { return 0; } hm_t *qb = *qbp; /* "qb" denotes the quotient basis storing the hash table entries. * "qb" is the basis itself from the last step, "nqb" are the new" * elements we generate in the current step. */ hm_t *nqb = NULL; /* dimensions of qb and nqb */ len_t qbd = 1; len_t nqbd = 1; // for entering first round in for loop deg_t deg = 0; const len_t nv = (*htp)->nv; exp_t ev[nv+1]; memset(ev, 0, (unsigned long)(nv+1) * sizeof(exp_t)); len_t *ind = calloc((unsigned long)nv, sizeof(len_t)); qb = (hm_t *)calloc((unsigned long)1, sizeof(hm_t)); qb[0] = check_lm_divisibility_and_insert_in_hash_table( ev, (*htp), bs); while (nqbd > 0 && deg < max_deg) { nqb = realloc(nqb, (sum(ind, nv) + nv) * sizeof(hm_t)); memset(nqb, 0, (sum(ind, nv) + nv) * sizeof(hm_t)); nqbd = generate_new_basis_elements(htp, nqb, qb, qbd, ind, bs); qb = realloc(qb, (unsigned long)(qbd + nqbd) * sizeof(hm_t)); /* printf("qb before adding\n"); * for (len_t ii = 0; ii < qbd; ++ii) { * printf("pos %u --> ", ii); * for (len_t jj = 0; jj <= nv; ++jj) { * printf("%d ", (*htp)->ev[qb[ii]][jj]); * } * printf("\n"); * } * printf("nqb before adding\n"); * for (len_t ii = 0; ii < nqbd; ++ii) { * printf("pos %u --> ", ii); * for (len_t jj = 0; jj <= nv; ++jj) { * printf("%d ", (*htp)->ev[nqb[ii]][jj]); * } * printf("\n"); * } */ memcpy(qb+qbd, nqb, (unsigned long)nqbd * sizeof(hm_t)); update_indices(ind, qb, qbd, nqbd, *htp); qbd += nqbd; deg++; /* printf("qb after adding\n"); for (len_t ii = 0; ii < qbd; ++ii) { printf("pos %u --> ", ii); for (len_t jj = 0; jj < (*htp)->evl; ++jj) { printf("%d ", (*htp)->ev[qb[ii]][jj]); } printf("\n"); } */ } free(nqb); free(ind); *qbp = qb; return qbd; } static void update_multipliers( hm_t **qdp, ht_t **bhtp, ht_t **shtp, bs_t *sat, md_t *st, const bs_t *bs, const deg_t max_deg ) { len_t i, j, k; len_t qdim = quotient_basis(qdp, bhtp, bs, max_deg); ht_t *bht = *bhtp; ht_t *sht = *shtp; bl_t ctr = 0; check_enlarge_basis(sat, qdim, st); hm_t *qb = *qdp; exp_t etmp[bht->evl]; memset(etmp, 0, (unsigned long)bht->evl * sizeof(exp_t)); /* remove elements that moved directly to kernel, i.e. monomials * added to the basis during the first stage of saturation * linear algebra */ for (i = 0; i < sat->ld; ++i) { if (sat->hm[i] != NULL) { sat->hm[ctr] = sat->hm[i]; sat->cf_32[ctr] = sat->cf_32[i]; sat->hm[ctr][COEFFS] = ctr; ctr++; } } sat->ld = ctr; ctr = 0; for (i = 0; i < sat->ld; ++i) { /* printf("qb[%u] = %u !=! %u (%u)\n", ctr, qb[ctr], i, sat->hm[i][MULT]); */ while (i < sat->ld && ctr < qdim && qb[ctr] != sat->hm[i][MULT]) { free(sat->hm[i]); sat->hm[i] = NULL; free(sat->cf_32[i]); sat->cf_32[i] = NULL; i++; } if (i < sat->ld) { sat->hm[ctr] = sat->hm[i]; sat->cf_32[ctr] = sat->cf_32[i]; sat->hm[ctr][COEFFS] = ctr; ctr++; } } sat->lo = ctr; /* Here we apply the simplify idea from F4: * Any of these new elements is a multiple of an element * of lower degree already handled. Thus we can use this * "divisor" instead of the initial saturation element sat[0]. */ for (i = ctr; i < qdim; ++i) { const hm_t m = qb[i]; const sdm_t ns = ~bht->hd[qb[i]].sdm; j = sat->lo-1; /* printf("sat->lo %u | j %u\n", sat->lo, j); */ sat_restart: while (j > 0 && bht->hd[sat->hm[j][MULT]].sdm & ns) { j--; } for (k = 0; k < bht->evl; ++k) { if (bht->ev[qb[i]][k] < bht->ev[sat->hm[j][MULT]][k]) { j--; goto sat_restart; } etmp[k] = bht->ev[qb[i]][k] - bht->ev[sat->hm[j][MULT]][k]; } const hi_t h = bht->hd[m].val - bht->hd[sat->hm[j][MULT]].val; sat->hm[i] = multiplied_poly_to_matrix_row( sht, bht, h, etmp, sat->hm[j]); sat->hm[i][MULT] = qb[i]; deg_t deg = bht->hd[sat->hm[i][OFFSET]].deg; if (st->nev > 0) { const len_t len = sat->hm[i][LENGTH]+OFFSET; for (j = OFFSET+1; j < len; ++j) { if (deg < bht->hd[sat->hm[i][j]].deg) { deg = bht->hd[sat->hm[i][j]].deg; } } } sat->hm[i][DEG] = deg; sat->cf_32[i] = (cf32_t *)malloc( (unsigned long)sat->hm[j][LENGTH] * sizeof(cf32_t)); memcpy(sat->cf_32[i], sat->cf_32[sat->hm[j][COEFFS]], (unsigned long)sat->hm[j][LENGTH] * sizeof(cf32_t)); sat->hm[i][COEFFS] = i; } /* AFTER mapping the new sat elements to sht we can map the old ones. * New ones may be generated by the old ones, so we have to keep the * monomials of the old ones in bht until all new ones are generated! */ for (i = 0; i < sat->lo; ++i) { while (sht->esz - sht->eld < sat->hm[i][LENGTH]) { enlarge_hash_table(sht); } for (j = OFFSET; j < sat->hm[i][LENGTH]+OFFSET; ++j) { sat->hm[i][j] = insert_in_hash_table(bht->ev[sat->hm[i][j]], sht); } } /* for (i = 0; i < sht->eld; ++i) { printf("sht[%u] = ", i); for (j = 0 ; j < sht->evl; ++j) { printf("%u ", sht->ev[i][j]); } printf("\n"); } */ sat->ld = qdim; st->new_multipliers = sat->ld - sat->lo; if (sat->mltdeg < max_deg) { sat->mltdeg = max_deg; } *bhtp = bht; *shtp = sht; } int core_f4sat( bs_t *gbs, bs_t *gsat, md_t *gmd, int32_t*errp ) { double ct = cputime(); double rt = realtime(); bs_t *bs = gbs; ht_t *bht = bs->ht; md_t *st = gmd; /* global saturation data */ len_t sat_test = 0; deg_t next_deg = 0; deg_t sat_deg = 0; /* elements to saturate input ideal with */ bs_t *sat = gsat; /* initialize multiplier of first element in sat to be the hash of * the all-zeroes exponent vector. */ memset(bht->ev[0], 0, (unsigned long)bht->evl * sizeof(exp_t)); sat->hm[0][MULT] = insert_in_hash_table(bht->ev[0], bht); sat->ld = 1; /* current quotient basis up to max lm degree in intermediate basis */ hm_t *qb = NULL; /* elements tracking reduction steps of tbr, being * added to bs if we find a linear dependency on * elements in tbr. They represent the multipliers * of the elements we saturate with. */ /* timings for one round */ double rrt, crt; /* initialize update hash table, symbolic hash table */ ht_t *sht = initialize_secondary_hash_table(bht, st); st->ht = sht; /* matrix holding sparse information generated * during symbolic preprocessing */ mat_t *mat = (mat_t *)calloc(1, sizeof(mat_t)); ps_t *ps = initialize_pairset(); st->ps = ps; st->hcm = (hi_t *)malloc(sizeof(hi_t)); /* hashes-to-columns maps for multipliers in saturation step */ hi_t *hcmm = (hi_t *)malloc(sizeof(hi_t)); int32_t round, i, j; st->max_gb_degree = INT32_MAX; /* elements of kernel in saturation step, to be added to basis bs */ bs_t *kernel = initialize_basis(st); /* reset bs->ld for first update process */ bs->ld = 0; /* move input generators to basis and generate first spairs. * always check redundancy since input generators may be redundant * even so they are homogeneous. */ update_basis_f4(ps, bs, bht, st, st->ngens); /* let's start the f4 rounds, we are done when no more spairs * are left in the pairset */ print_round_information_header(stdout, st); round = 1; end_sat_step: for (; ps->ld > 0; ++round) { rrt = realtime(); crt = cputime(); st->max_bht_size = st->max_bht_size > bht->esz ? st->max_bht_size : bht->esz; st->current_rd = round; /* preprocess data for next reduction round */ select_spairs_by_minimal_degree(mat, bs, st); symbolic_preprocessing(mat, bs, st); convert_hashes_to_columns(mat, st, sht); sort_matrix_rows_decreasing(mat->rr, mat->nru); sort_matrix_rows_increasing(mat->tr, mat->nrl); /* linear algebra, depending on choice, see set_function_pointers() */ linear_algebra(mat, bs, bs, st); /* columns indices are mapped back to exponent hashes */ if (mat->np > 0) { convert_sparse_matrix_rows_to_basis_elements( -1, mat, bs, bht, sht, st); sat_test++; } clean_hash_table(sht); /* add lead monomials to trace, stores hashes in basis hash * table which is used in all upcoming F4 runs */ /* if (mat->np > 0) { * add_lms_to_trace(trace, bs, mat->np); * trace->ltd++; * } */ /* all rows in mat are now polynomials in the basis, * so we do not need the rows anymore */ clear_matrix(mat); /* check redundancy only if input is not homogeneous */ update_basis_f4(ps, bs, bht, st, mat->np); if (bs->constant == 1) { printf("basis is constant\n"); ps->ld = 0; break; } clean_hash_table(sht); print_round_timings(stdout, st, rrt, crt); /* saturation step starts here */ if ((bs->mltdeg >= sat->hm[0][DEG] && sat_test != 0) || ps->ld == 0) { /* if (bs->mltdeg - next_deg == 0 || ps->ld == 0) { */ /* if (sat_done == 0 && (sat_test % 3 == 0 || ps->ld == 0)) { */ if (st->nr_kernel_elts > 0 && ps->ld == 0 && is_zero_dimensional(bs, bht) && is_already_saturated( bs, sat, mat, &bht, &sht, st)) { /* sat_done = 1; */ goto end_sat_step; } /* check for new elements to be tested for adding saturation * information to the intermediate basis */ if (ps->ld != 0) { sat_deg = 2*bs->mltdeg/3; } else { sat_deg = bs->mltdeg; } len_t bld = bs->ld; for (deg_t ii = next_deg; ii < sat_deg; ++ii) { rrt = realtime(); crt = cputime(); /* printf("sat->deg %u\n", sat_deg); */ update_multipliers(&qb, &bht, &sht, sat, st, bs, ii); /* check for monomial multiples of elements from saturation list */ select_saturation(sat, mat, st, sht, bht); symbolic_preprocessing(mat, bs, st); /* It may happen that there is no reducer at all for the * saturation elements, then nothing has to be done. */ if (mat->nru > 0) { if (st->info_level > 1) { /* printf("kernel computation "); */ printf("%3u compute kernel", sat_deg); } convert_hashes_to_columns_sat(mat, sat, st, sht); convert_multipliers_to_columns(&hcmm, sat, st, bht); sort_matrix_rows_decreasing(mat->rr, mat->nru); compute_kernel_sat_ff_32(sat, mat, kernel, bs, st); if (st->info_level > 1) { printf("%56d new kernel elements", kernel->ld); fflush(stdout); } if (kernel->ld > 0) { if (st->info_level > 1) { printf("\n "); } clear_matrix(mat); /* interreduce kernel */ copy_kernel_to_matrix(mat, kernel, sat->ld); /* linear algebra, depending on choice, see set_function_pointers() */ probabilistic_sparse_linear_algebra_ff_32(mat, kernel, kernel, st); /* linear_algebra(mat, kernel, st); */ /* columns indices are mapped back to exponent hashes */ if (mat->np > 0) { /* we need to use the right hcmm */ hi_t *tmp = st->hcm; st->hcm = hcmm; convert_sparse_matrix_rows_to_basis_elements_use_sht( -1, mat, bs, bs->ht, st); st->hcm = tmp; } st->nr_kernel_elts += kernel->ld; sat_test = 0; free_kernel_coefficients(kernel); update_basis_f4(ps, bs, bht, st, mat->np); kernel->ld = 0; if (st->info_level > 1) { printf(" "); } } /* all rows in mat are now polynomials in the basis, * so we do not need the rows anymore */ convert_columns_to_hashes(sat, st, hcmm); for (i = 0; i < sat->ld; ++i) { bht->hd[hcmm[i]].idx = 0; } } clear_matrix(mat); /* move hashes for sat entries from sht back to bht */ for (i = 0; i < sat->ld; ++i) { if (sat->hm[i] != NULL) { while (bht->esz - bht->eld < sat->hm[i][LENGTH]) { enlarge_hash_table(bht); } for (j = OFFSET; j < sat->hm[i][LENGTH]+OFFSET; ++j) { sat->hm[i][j] = insert_in_hash_table( sht->ev[sat->hm[i][j]], bht); } deg_t deg = bht->hd[sat->hm[i][OFFSET]].deg; if (st->nev > 0) { const len_t len = sat->hm[i][LENGTH]+OFFSET; for (j = OFFSET+1; j < len; ++j) { if (deg < bht->hd[sat->hm[i][j]].deg) { deg = bht->hd[sat->hm[i][j]].deg; } } } sat->hm[i][DEG] = deg; } } clean_hash_table(sht); print_sat_round_timings(stdout, st, rrt, crt); if (bld != bs->ld) { next_deg = ii; goto end_sat_step; } } next_deg = sat_deg; } } print_round_information_footer(stdout, st); /* remove possible redudant elements */ final_remove_redundant_elements(bs, st, bht); /* reduce final basis? */ if (st->reduce_gb == 1) { /* note: bht will become sht, and sht will become NULL, * thus we need pointers */ reduce_basis(bs, mat, st); } st->f4_rtime = realtime() - rt; st->f4_ctime = cputime() - ct; get_and_print_final_statistics(stdout, st, bs); /* printf("basis has %u elements.\n", bs->lml); * * for (i = 0; i < bs->lml; ++i) { * for (j = 0; j < bht->nv; ++j) { * printf("%u ", bht->ev[bs->hm[bs->lmps[i]][OFFSET]][j]); * } * printf("\n"); * } */ /* free and clean up */ free(hcmm); free(qb); free_basis_elements(sat); free_basis_without_hash_table(&sat); free_basis(&kernel); /* note that all rows kept from mat during the overall computation are * basis elements and thus we do not need to free the rows itself, but * just the matrix structure */ free(mat); if (sht != NULL) { free_hash_table(&sht); } if (ps != NULL) { free_pairset(&ps); } return 1; } msolve-0.6.5/src/neogb/f4sat.h000066400000000000000000000016451456710632100161150ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef GB_F4SAT_H #define GB_F4SAT_H #include "data.h" #include "f4.h" int core_f4sat( bs_t *gbs, bs_t *gsat, md_t *gmd, int32_t*errp ); #endif msolve-0.6.5/src/neogb/gb.c000066400000000000000000000041511456710632100154520ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "libneogb.h" #include "data.c" #include "meta_data.c"/* computational meta data */ #include "tools.c" /* tools like inversion mod p, * tracer construction, timings etc. */ #include "sort_r.h" /* special quicksort implementation */ #include "hash.c" /* hash table stuff */ #include "order.c" /* order and comparison procedures */ #include "basis.c" /* basis and polynomial handling */ #include "la_ff_8.c" /* finite field linear algebra (8 bit) */ #include "la_ff_16.c" /* finite field linear algebra (16 bit) */ #include "la_ff_32.c" /* finite field linear algebra (32 bit) */ #include "la_qq.c" /* rational linear algebra */ #include "update.c" /* update process and pairset handling */ #include "convert.c" /* conversion between hashes and column indices*/ #include "symbol.c" /* symbolic preprocessing */ #include "io.c" /* input and output data handling */ #include "engine.c" /* global, shared parts of gb engine */ #include "f4.c" /* implemenation of f4 algorithm */ #include "sba.c" /* implemenation of sba algorithm */ #include "nf.c" /* implemenation of normal form algorithm */ #include "f4sat.c" /* implemenation of saturation algorithm */ #include "modular.c" /* implemenation of modular Groebner for F4 */ msolve-0.6.5/src/neogb/hash.c000066400000000000000000001074411456710632100160130ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "hash.h" /* we have three different hash tables: * 1. one hash table for elements in the basis (bht) * 2. one hash table for the spairs during the update process (uht) * 3. one hash table for the multiplied elements during symbolic * preprocessing (sht) */ /* The idea of the structure of the hash table is taken from an * implementation by Roman Pearce and Michael Monagan in Maple. */ static val_t pseudo_random_number_generator( uint32_t *seed ) { uint32_t rseed = *seed; rseed ^= (rseed << 13); rseed ^= (rseed >> 17); rseed ^= (rseed << 5); *seed = rseed; return (val_t)rseed; } ht_t *initialize_basis_hash_table( md_t *st ) { len_t i; hl_t j; const len_t nv = st->nvars; ht_t *ht = (ht_t *)malloc(sizeof(ht_t)); ht->nv = nv; /* generate map */ ht->bpv = (len_t)((CHAR_BIT * sizeof(sdm_t)) / (unsigned long)nv); if (ht->bpv == 0) { ht->bpv++; } ht->ndv = (unsigned long)nv < (CHAR_BIT * sizeof(sdm_t)) ? nv : (len_t)((CHAR_BIT * sizeof(sdm_t))); ht->dv = (len_t *)calloc((unsigned long)ht->ndv, sizeof(len_t)); ht->hsz = (hl_t)pow(2, st->init_hts); ht->esz = ht->hsz / 2; ht->hmap = calloc(ht->hsz, sizeof(hi_t)); if (st->nev == 0) { ht->evl = nv + 1; /* store also degree at first position */ ht->ebl = 0; for (i = 1; i <= ht->ndv; ++i) { ht->dv[i-1] = i; } } else { ht->evl = nv + 2; /* store also degrees for both blocks, see * data.h for more on exponent vector structure */ ht->ebl = st->nev + 1; /* store also degree at first position */ if (st->nev >= ht->ndv) { for (i = 1; i <= ht->ndv; ++i) { ht->dv[i-1] = i; } } else { len_t ctr = 0; for (i = 1; i <= st->nev; ++i) { ht->dv[ctr++] = i; } for (i = ht->ebl+1; i < ht->ndv+2; ++i) { ht->dv[ctr++] = i; } } } /* generate divmask map */ ht->dm = (sdm_t *)calloc( (unsigned long)(ht->ndv * ht->bpv), sizeof(sdm_t)); /* generate random values */ ht->rsd = 2463534242; ht->rn = calloc((unsigned long)ht->evl, sizeof(val_t)); for (i = ht->evl; i > 0; --i) { /* random values should not be zero */ ht->rn[i-1] = pseudo_random_number_generator(&(ht->rsd)) | 1; } /* generate exponent vector */ /* keep first entry empty for faster divisibility checks */ ht->eld = 1; ht->hd = (hd_t *)calloc(ht->esz, sizeof(hd_t)); ht->ev = (exp_t **)malloc(ht->esz * sizeof(exp_t *)); if (ht->ev == NULL) { fprintf(stderr, "Computation needs too much memory on this machine,\n"); fprintf(stderr, "could not initialize exponent vector for hash table,\n"); fprintf(stderr, "esz = %lu, segmentation fault will follow.\n", (unsigned long)ht->esz); } exp_t *tmp = (exp_t *)malloc( (unsigned long)ht->evl * ht->esz * sizeof(exp_t)); if (tmp == NULL) { fprintf(stderr, "Exponent storage needs too much memory on this machine,\n"); fprintf(stderr, "initialization failed, esz = %lu,\n", (unsigned long)ht->esz); fprintf(stderr, "segmentation fault will follow.\n"); } const hl_t esz = ht->esz; for (j = 0; j < esz; ++j) { ht->ev[j] = tmp + (j*ht->evl); } st->max_bht_size = ht->esz; return ht; } ht_t *copy_hash_table( const ht_t *bht ) { hl_t j; ht_t *ht = (ht_t *)malloc(sizeof(ht_t)); ht->nv = bht->nv; ht->evl = bht->evl; ht->ebl = bht->ebl; ht->hsz = bht->hsz; ht->esz = bht->esz; ht->hmap = calloc(ht->hsz, sizeof(hi_t)); memcpy(ht->hmap, bht->hmap, (unsigned long)ht->hsz * sizeof(hi_t)); ht->ndv = bht->ndv; ht->bpv = bht->bpv; ht->dm = bht->dm; ht->rn = bht->rn; ht->dv = (len_t *)calloc((unsigned long)ht->ndv, sizeof(len_t)); memcpy(ht->dv, bht->dv, (unsigned long)ht->ndv * sizeof(len_t)); /* generate exponent vector */ /* keep first entry empty for faster divisibility checks */ ht->hd = (hd_t *)calloc(ht->esz, sizeof(hd_t)); memcpy(ht->hd, bht->hd, (unsigned long)ht->esz * sizeof(hd_t)); ht->ev = (exp_t **)malloc(ht->esz * sizeof(exp_t *)); if (ht->ev == NULL) { fprintf(stderr, "Computation needs too much memory on this machine,\n"); fprintf(stderr, "could not initialize exponent vector for hash table,\n"); fprintf(stderr, "esz = %lu, segmentation fault will follow.\n", (unsigned long)ht->esz); } exp_t *tmp = (exp_t *)malloc( (unsigned long)ht->evl * ht->esz * sizeof(exp_t)); if (tmp == NULL) { fprintf(stderr, "Exponent storage needs too much memory on this machine,\n"); fprintf(stderr, "initialization failed, esz = %lu,\n", (unsigned long)ht->esz); fprintf(stderr, "segmentation fault will follow.\n"); } memcpy(tmp, bht->ev[0], (unsigned long)ht->evl * ht->esz * sizeof(exp_t)); ht->eld = bht->eld; const hl_t esz = ht->esz; for (j = 0; j < esz; ++j) { ht->ev[j] = tmp + (j*ht->evl); } return ht; } ht_t *initialize_secondary_hash_table( const ht_t * const bht, const md_t * const md ) { hl_t j; ht_t *ht = (ht_t *)malloc(sizeof(ht_t)); ht->nv = bht->nv; ht->evl = bht->evl; ht->ebl = bht->ebl; /* generate map */ int32_t min = 3 > md->init_hts-5 ? 3 : md->init_hts-5; ht->hsz = (hl_t)pow(2, min); ht->esz = ht->hsz / 2; ht->hmap = calloc(ht->hsz, sizeof(hi_t)); /* divisor mask and random number seeds from basis hash table */ ht->ndv = bht->ndv; ht->bpv = bht->bpv; ht->dm = bht->dm; ht->rn = bht->rn; ht->dv = bht->dv; /* generate exponent vector */ /* keep first entry empty for faster divisibility checks */ ht->eld = 1; ht->hd = (hd_t *)calloc(ht->esz, sizeof(hd_t)); ht->ev = (exp_t **)malloc(ht->esz * sizeof(exp_t *)); if (ht->ev == NULL) { fprintf(stderr, "Computation needs too much memory on this machine,\n"); fprintf(stderr, "could not initialize exponent vector for hash table,\n"); fprintf(stderr, "esz = %lu, segmentation fault will follow.\n", (unsigned long)ht->esz); } exp_t *tmp = (exp_t *)malloc( (unsigned long)ht->evl * ht->esz * sizeof(exp_t)); if (tmp == NULL) { fprintf(stderr, "Exponent storage needs too much memory on this machine,\n"); fprintf(stderr, "initialization failed, esz = %lu,\n", (unsigned long)ht->esz); fprintf(stderr, "segmentation fault will follow.\n"); } const hl_t esz = ht->esz; for (j = 0; j < esz; ++j) { ht->ev[j] = tmp + (j*ht->evl); } return ht; } void free_shared_hash_data( ht_t *ht ) { if (ht != NULL) { if (ht->rn) { free(ht->rn); ht->rn = NULL; } if (ht->dv) { free(ht->dv); ht->dv = NULL; } if (ht->dm) { free(ht->dm); ht->dm = NULL; } } } void free_hash_table( ht_t **htp ) { ht_t *ht = *htp; if (ht->hmap) { free(ht->hmap); ht->hmap = NULL; } if (ht->hd) { free(ht->hd); ht->hd = NULL; } if (ht->ev) { /* note: memory is allocated as one big block, * so freeing ev[0] is enough */ free(ht->ev[0]); free(ht->ev); ht->ev = NULL; } free(ht); ht = NULL; *htp = ht; } void full_free_hash_table( ht_t **htp ) { ht_t *ht = *htp; if (ht->hmap) { free(ht->hmap); ht->hmap = NULL; } if (ht->hd) { free(ht->hd); ht->hd = NULL; } if (ht->ev) { /* note: memory is allocated as one big block, * so freeing ev[0] is enough */ free(ht->ev[0]); free(ht->ev); ht->ev = NULL; } if (ht != NULL) { if (ht->rn) { free(ht->rn); ht->rn = NULL; } if (ht->dv) { free(ht->dv); ht->dv = NULL; } if (ht->dm) { free(ht->dm); ht->dm = NULL; } } free(ht); ht = NULL; *htp = ht; } /* we just double the hash table size */ static void enlarge_hash_table( ht_t *ht ) { hl_t i, j; val_t h, k; ht->esz = 2 * ht->esz; const hl_t esz = ht->esz; const hi_t eld = ht->eld; ht->hd = realloc(ht->hd, esz * sizeof(hd_t)); memset(ht->hd+eld, 0, (esz-eld) * sizeof(hd_t)); ht->ev = realloc(ht->ev, esz * sizeof(exp_t *)); if (ht->ev == NULL) { fprintf(stderr, "Enlarging hash table failed for esz = %lu,\n", (unsigned long)esz); fprintf(stderr, "segmentation fault will follow.\n"); } /* note: memory is allocated as one big block, so reallocating * memory from ev[0] is enough */ ht->ev[0] = realloc(ht->ev[0], esz * (unsigned long)ht->evl * sizeof(exp_t)); if (ht->ev[0] == NULL) { fprintf(stderr, "Enlarging exponent vector for hash table failed\n"); fprintf(stderr, "for esz = %lu, segmentation fault will follow.\n", (unsigned long)esz); } /* due to realloc we have to reset ALL ev entries, * memory might have been moved */ for (i = 1; i < esz; ++i) { ht->ev[i] = ht->ev[0] + (i*ht->evl); } /* The hash table should be double the size of the exponent space in * order to never get a fill in over 50%. If the exponent size is now * enlarge to 2^31 elements that's the limit we can go. Thus we cannot * enlarge the hash table size any further and have to live with more * than 50% fill in. */ if (ht->hsz < (hl_t)pow(2,32)) { ht->hsz = 2 * ht->hsz; const hl_t hsz = ht->hsz; ht->hmap = realloc(ht->hmap, hsz * sizeof(hi_t)); if (ht->hmap == NULL) { fprintf(stderr, "Enlarging hash table failed for hsz = %lu,\n", (unsigned long)hsz); fprintf(stderr, "segmentation fault will follow.\n"); } memset(ht->hmap, 0, hsz * sizeof(hi_t)); const hi_t mod = (hi_t )(hsz-1); /* reinsert known elements */ for (i = 1; i < eld; ++i) { h = ht->hd[i].val; /* probing */ k = h; for (j = 0; j < hsz; ++j) { k = (k+j) & mod; if (ht->hmap[k]) { continue; } ht->hmap[k] = i; break; } } } else { if (ht->hsz == (hl_t)pow(2,32)) { printf("Exponent space is now 2^32 elements wide, we cannot\n"); printf("enlarge the hash table any further, thus fill in gets\n"); printf("over 50%% and performance of hashing may get worse.\n"); } else { printf("Hash table is full, we can no longer enlarge\n"); printf("Segmentation fault will follow.\n"); free(ht->hmap); ht->hmap = NULL; } } } static inline sdm_t generate_short_divmask( const exp_t * const a, const ht_t *ht ) { len_t i, j; int32_t res = 0; int32_t ctr = 0; const len_t ndv = ht->ndv; const len_t * const dv = ht->dv; const len_t bpv = ht->bpv; for (i = 0; i < ndv; ++i) { for (j = 0; j < bpv; ++j) { if ((sdm_t)a[dv[i]] >= ht->dm[ctr]) { res |= 1 << ctr; } ctr++; } } return res; } /* note: we calculate the divmask after reading in the input generators. thoseV * are first stored in the local hash table. thus we use the local exponents to * generate the divmask */ void calculate_divmask( ht_t *ht ) { hi_t i; hl_t k; len_t j, steps; int32_t ctr = 0; const len_t * const dv = ht->dv; exp_t **ev = ht->ev; deg_t *max_exp = (deg_t *)malloc((unsigned long)ht->ndv * sizeof(deg_t)); deg_t *min_exp = (deg_t *)malloc((unsigned long)ht->ndv * sizeof(deg_t)); exp_t *e = ev[1]; /* get initial values from first hash table entry */ for (i = 0; i < ht->ndv; ++i) { max_exp[i] = min_exp[i] = e[dv[i]]; } /* get maximal and minimal exponent element entries in hash table */ for (i = 2; i < ht->eld; ++i) { e = ev[i]; for (j = 0; j < ht->ndv; ++j) { if (e[dv[j]] > max_exp[j]) { max_exp[j] = e[dv[j]]; continue; } if (e[dv[j]] < min_exp[j]) { min_exp[j] = e[dv[j]]; } } } /* calculate average values for generating divmasks */ for (i = 0; i < ht->ndv; ++i) { steps = (max_exp[i] - min_exp[i]) / ht->bpv; if (steps == 0) steps++; for (j = 0; j < ht->bpv; ++j) { ht->dm[ctr++] = (sdm_t)steps++; } } /* initialize divmasks for elements already added to hash table */ for (k = 1; k < ht->eld; k++) { ht->hd[k].sdm = generate_short_divmask(ev[k], ht); } free(max_exp); free(min_exp); } /* returns zero if a is not divisible by b, else 1 is returned */ static inline hi_t check_monomial_division( const hi_t a, const hi_t b, const ht_t *ht ) { len_t i; /* short divisor mask check */ if (ht->hd[b].sdm & ~ht->hd[a].sdm) { return 0; } const len_t evl = ht->evl; const exp_t *const ea = ht->ev[a]; const exp_t *const eb = ht->ev[b]; /* printf("! no sdm decision !\n"); */ /* exponent check */ for (i = 0; i < evl-1; i += 2) { if (ea[i] < eb[i] || ea[i+1] < eb[i+1]) { return 0; } } if (ea[evl-1] < eb[evl-1]) { return 0; } return 1; } static inline void check_monomial_division_in_update( hi_t *a, const len_t start, const len_t end, const hi_t b, const ht_t *ht ) { len_t i, j; const len_t evl = ht->evl; const sdm_t sb = ht->hd[b].sdm; const exp_t *const eb = ht->ev[b]; /* pairs are sorted, we only have to search entries * above the starting point */ j = start+1; restart: for (; j < end; ++j) { if (a[j] == 0) { continue; } /* short divisor mask check */ if (~ht->hd[a[j]].sdm & sb) { continue; } const exp_t *const ea = ht->ev[a[j]]; /* exponent check */ for (i = 0; i < evl-1; i += 2) { if (ea[i] < eb[i] || ea[i+1] < eb[i+1]) { j++; goto restart; } } if (ea[evl-1] < eb[evl-1]) { continue; } a[j] = 0; } } static inline hi_t check_lm_divisibility_and_insert_in_hash_table( const exp_t *a, ht_t *ht, const bs_t * const bs ) { hl_t i; hi_t k, pos; len_t j; exp_t *e; hd_t *d; const len_t lml = bs->lml; const sdm_t * const lms = bs->lm; const bl_t * const lmps = bs->lmps; const sdm_t nsdm = ~generate_short_divmask(a, ht); val_t h = 0; const len_t evl = ht->evl; const hl_t hsz = ht->hsz; /* ht->hsz <= 2^32 => mod is always uint32_t */ const hi_t mod = (hi_t)(ht->hsz - 1); /* check divisibility w.r.t. current lead monomials */ i = 0; start: while (i < lml && lms[i] & nsdm) { i++; } if (i < lml) { e = ht->ev[bs->hm[lmps[i]][OFFSET]]; for (j = 0; j < evl; ++j) { if (e[j] > a[j]) { i++; goto start; } } /* divisible by lm */ return 0; } /* if we are here then a is not divisible by a current * lead monomial and we can add it to the hash table */ /* generate hash value */ for (j = 0; j < evl; ++j) { h += ht->rn[j] * a[j]; } /* probing */ k = h; i = 0; restart: for (; i < hsz; ++i) { k = (hi_t)((k+i) & mod); const hi_t hm = ht->hmap[k]; if (!hm) { break; } if (ht->hd[hm].val != h) { continue; } const exp_t * const ehm = ht->ev[hm]; for (j = 0; j < evl-1; j += 2) { if (a[j] != ehm[j] || a[j+1] != ehm[j+1]) { i++; goto restart; } } if (a[evl-1] != ehm[evl-1]) { i++; goto restart; } return hm; } /* add element to hash table */ ht->hmap[k] = pos = (hi_t)ht->eld; e = ht->ev[pos]; d = ht->hd + pos; memcpy(e, a, (unsigned long)evl * sizeof(exp_t)); d->sdm = generate_short_divmask(e, ht); d->deg = e[0]; d->deg += ht->ebl > 0 ? e[ht->ebl] : 0; d->val = h; ht->eld++; return pos; } static inline hi_t insert_multiplied_signature_in_hash_table( const hm_t h1, const hm_t h2, ht_t *ht ) { hl_t i; hi_t k, pos; len_t j; exp_t *e; exp_t *a = ht->ev[0]; hd_t *d; val_t h = 0; const len_t evl = ht->evl; const hl_t hsz = ht->hsz; /* ht->hsz <= 2^32 => mod is always uint32_t */ const hi_t mod = (hi_t)(ht->hsz - 1); h = h1 + h2; /* generate exponent vector */ for (j = 0; j < evl; ++j) { a[j] = ht->ev[h1][j] + ht->ev[h2][j]; } /* probing */ k = h; i = 0; restart: for (; i < hsz; ++i) { k = (hi_t)((k+i) & mod); const hi_t hm = ht->hmap[k]; if (!hm) { break; } if (ht->hd[hm].val != h) { continue; } const exp_t * const ehm = ht->ev[hm]; for (j = 0; j < evl-1; j += 2) { if (a[j] != ehm[j] || a[j+1] != ehm[j+1]) { i++; goto restart; } } if (a[evl-1] != ehm[evl-1]) { i++; goto restart; } return hm; } /* add element to hash table */ ht->hmap[k] = pos = (hi_t)ht->eld; e = ht->ev[pos]; d = ht->hd + pos; memcpy(e, a, (unsigned long)evl * sizeof(exp_t)); d->sdm = generate_short_divmask(e, ht); d->deg = e[0]; d->deg += ht->ebl > 0 ? e[ht->ebl] : 0; d->val = h; ht->eld++; return pos; } /* If the exponent vector is not contained in the hash table * we return 0 and hp is a pointer to the hash value and kp is * a pointer to the index of hmap where to store the exponent. * If the exponent vector is contained in the hash table we * return 1 and kp is the pointer of the index where the * exponent vector is stored in the exponents array of the * hash table. */ static inline int32_t is_contained_in_hash_table( const exp_t *a, const ht_t * const ht, const val_t h, hi_t *kp ) { hl_t i; hi_t k; len_t j; /* const len_t evl = ht->evl; * const hl_t hsz = ht->hsz; */ /* ht->hsz <= 2^32 => mod is always uint32_t */ const hi_t mod = (hi_t)(ht->hsz - 1); /* probing */ k = h; i = 0; restart: for (; i < ht->hsz; ++i) { k = (hi_t)((k+i) & mod); const hi_t hm = ht->hmap[k]; if (!hm) { *kp = k; return 0; } if (ht->hd[hm].val != h) { continue; } const exp_t * const ehm = ht->ev[hm]; for (j = 0; j < ht->evl-1; j += 2) { if (a[j] != ehm[j] || a[j+1] != ehm[j+1]) { i++; goto restart; } } if (a[ht->evl-1] != ehm[ht->evl-1]) { i++; goto restart; } *kp = hm; return 1; } return -1; } /* This function assumes that is_contained_in_hash_table() was * called beforehand such that the values for h and k are already * precomputed. */ static inline len_t add_to_hash_table( const exp_t * const a, const val_t h, const hi_t k, ht_t *ht ) { /* add element to hash table */ hi_t pos; ht->hmap[k] = pos = (hi_t)ht->eld; exp_t *e = ht->ev[pos]; hd_t *d = ht->hd + pos; memcpy(e, a, (unsigned long)ht->evl * sizeof(exp_t)); d->sdm = generate_short_divmask(e, ht); d->deg = e[0]; d->deg += ht->ebl > 0 ? e[ht->ebl] : 0; d->val = h; ht->eld++; return pos; } static inline len_t check_insert_in_hash_table( const exp_t *a, val_t h, ht_t *ht ) { if (h == 0) { /* generate hash value */ for (len_t j = 0; j < ht->evl; ++j) { h += ht->rn[j] * a[j]; } } hi_t k = 0; #if 1 len_t ld = 0; while (1) { ld = ht->eld; if (is_contained_in_hash_table(a, ht, h, &k)) { return k; } else { if (ht->eld == ld) { #pragma omp critical ld = add_to_hash_table(a, h, k, ht); return ld; } } } #else return is_contained_in_hash_table(a, ht, h, &k) ? k : add_to_hash_table(a, h, k, ht); #endif } static inline hi_t insert_in_hash_table( const exp_t *a, ht_t *ht ) { hl_t i; hi_t k, pos; len_t j; exp_t *e; hd_t *d; val_t h = 0; const len_t evl = ht->evl; const hl_t hsz = ht->hsz; /* ht->hsz <= 2^32 => mod is always uint32_t */ const hi_t mod = (hi_t)(ht->hsz - 1); /* generate hash value */ for (j = 0; j < evl; ++j) { h += ht->rn[j] * a[j]; } /* probing */ k = h; i = 0; restart: for (; i < hsz; ++i) { k = (hi_t)((k+i) & mod); const hi_t hm = ht->hmap[k]; if (!hm) { break; } if (ht->hd[hm].val != h) { continue; } const exp_t * const ehm = ht->ev[hm]; for (j = 0; j < evl-1; j += 2) { if (a[j] != ehm[j] || a[j+1] != ehm[j+1]) { i++; goto restart; } } if (a[evl-1] != ehm[evl-1]) { i++; goto restart; } return hm; } /* add element to hash table */ ht->hmap[k] = pos = (hi_t)ht->eld; e = ht->ev[pos]; d = ht->hd + pos; memcpy(e, a, (unsigned long)evl * sizeof(exp_t)); d->sdm = generate_short_divmask(e, ht); d->deg = e[0]; d->deg += ht->ebl > 0 ? e[ht->ebl] : 0; d->val = h; ht->eld++; return pos; } static inline void reinitialize_hash_table( ht_t *ht, const hl_t size ) { hl_t i; /* is there still enough space in the local table? */ if (size >= (ht->esz)) { while (size >= ht->esz) { ht->esz = 2 * ht->esz; ht->hsz = 2 * ht->hsz; } const hl_t esz = ht->esz; const hl_t hsz = ht->hsz; const len_t evl = ht->evl; ht->hd = realloc(ht->hd, esz * sizeof(hd_t)); ht->ev = realloc(ht->ev, esz * sizeof(exp_t *)); if (ht->ev == NULL) { fprintf(stderr, "Computation needs too much memory on this machine,\n"); fprintf(stderr, "could not reinitialize exponent vector for hash table,\n"); fprintf(stderr, "esz = %lu, segmentation fault will follow.\n", (unsigned long)esz); } /* note: memory is allocated as one big block, so reallocating * memory from evl[0] is enough */ ht->ev[0] = realloc(ht->ev[0], esz * (unsigned long)evl * sizeof(exp_t)); if (ht->ev[0] == NULL) { fprintf(stderr, "Exponent storage needs too much memory on this machine,\n"); fprintf(stderr, "reinitialization failed, esz = %lu\n", (unsigned long)esz); fprintf(stderr, "segmentation fault will follow.\n"); } /* due to realloc we have to reset ALL evl entries, memory might be moved */ for (i = 1; i < esz; ++i) { ht->ev[i] = ht->ev[0] + (i*evl); } ht->hmap = realloc(ht->hmap, hsz * sizeof(hi_t)); } memset(ht->hd, 0, ht->esz * sizeof(hd_t)); memset(ht->hmap, 0, ht->hsz * sizeof(hi_t)); ht->eld = 1; } static inline void clean_hash_table( ht_t *ht ) { memset(ht->hd, 0, ht->esz * sizeof(hd_t)); memset(ht->hmap, 0, ht->hsz * sizeof(hi_t)); ht->eld = 1; } static inline int prime_monomials( const hi_t a, const hi_t b, const ht_t *ht ) { len_t i; const exp_t * const ea = ht->ev[a]; const exp_t * const eb = ht->ev[b]; const len_t evl = ht->evl; const len_t ebl = ht->ebl; for (i = 1; i < ebl; ++i) { if (ea[i] != 0 && eb[i] != 0) { return 0; } } for (i = ebl+1; i < evl; ++i) { if (ea[i] != 0 && eb[i] != 0) { return 0; } } return 1; } static inline void insert_plcms_in_basis_hash_table( ps_t *psl, spair_t *pp, ht_t *bht, const ht_t *uht, const bs_t * const bs, const hi_t * const lcms, const len_t start, const len_t end ) { hl_t i; hi_t k, pos; len_t j, l, m; hd_t *d; spair_t *ps = psl->p; const len_t evl = bht->evl; const hl_t hsz = bht->hsz; /* ht->hsz <= 2^32 => mod is always uint32_t */ const hi_t mod = (hi_t)(hsz - 1); hm_t * const * const hm = bs->hm; m = start; l = 0; letsgo: for (; l < end; ++l) { if (lcms[l] == 0) { continue; } if (prime_monomials( hm[pp[l].gen1][OFFSET], hm[pp[0].gen2][OFFSET], bht)) { continue; } ps[m] = pp[l]; const val_t h = uht->hd[lcms[l]].val; memcpy(bht->ev[bht->eld], uht->ev[lcms[l]], (unsigned long)evl * sizeof(exp_t)); const exp_t * const n = bht->ev[bht->eld]; k = h; i = 0; restart: for (; i < hsz; ++i) { k = (hi_t)(k+i) & mod; const hi_t hm = bht->hmap[k]; if (!hm) { break; } if (bht->hd[hm].val != h) { continue; } const exp_t * const ehm = bht->ev[hm]; for (j = 0; j < evl-1; j += 2) { if (n[j] != ehm[j] || n[j+1] != ehm[j+1]) { i++; goto restart; } } if (n[evl-1] != ehm[evl-1]) { i++; goto restart; } ps[m++].lcm = hm; l++; goto letsgo; } /* add element to hash table */ bht->hmap[k] = pos = (hi_t)bht->eld; d = bht->hd + bht->eld; d->sdm = uht->hd[lcms[l]].sdm; d->deg = uht->hd[lcms[l]].deg; d->val = h; bht->eld++; ps[m++].lcm = pos; } psl->ld = m; } static inline void switch_hcm_data_to_basis_hash_table( hi_t *hcm, ht_t *bht, const mat_t *mat, const ht_t * const sht ) { const len_t start = mat->ncl; const len_t end = mat->nc; while (bht->esz - bht->eld < mat->ncr) { enlarge_hash_table(bht); } for (len_t i = start; i < end; ++i) { #if PARALLEL_HASHING hcm[i] = check_insert_in_hash_table( sht->ev[hcm[i]], sht->hd[hcm[i]].val, bht); #else hcm[i] = insert_in_hash_table(sht->ev[hcm[i]], bht); #endif } } static inline void insert_in_basis_hash_table_pivots( hm_t *row, ht_t *bht, const ht_t * const sht, const hi_t * const hcm, const md_t * const st ) { len_t l; /* while (bht->esz - bht->eld < row[LENGTH]) { enlarge_hash_table(bht); } */ const len_t len = row[LENGTH]+OFFSET; const len_t evl = bht->evl; const hd_t * const hds = sht->hd; exp_t * const * const evs = sht->ev; exp_t *evt = (exp_t *)malloc( (unsigned long)(st->nthrds * evl) * sizeof(exp_t)); /* #if PARALLEL_HASHING #pragma omp parallel for num_threads(st->nthrds) \ private(l) #endif */ for (l = OFFSET; l < len; ++l) { exp_t *evtl = evt + (omp_get_thread_num() * evl); memcpy(evtl, evs[hcm[row[l]]], (unsigned long)evl * sizeof(exp_t)); #if PARALLEL_HASHING const val_t h = hds[hcm[row[l]]].val; row[l] = check_insert_in_hash_table(evtl, h, bht); #else row[l] = insert_in_hash_table(evtl, bht); #endif } free(evt); } static inline void insert_poly_in_hash_table( hm_t *row, const hm_t * const b, const ht_t * const ht1, ht_t *ht2 ) { len_t l; const len_t len = b[LENGTH]+OFFSET; l = OFFSET; for (; l < len; ++l) { #if PARALLEL_HASHING row[l] = check_insert_in_hash_table(ht1->ev[b[l]], ht1->hd[b[l]].val, ht2); #else row[l] = insert_in_hash_table(ht1->ev[b[l]], ht2); #endif } } static inline void insert_multiplied_poly_in_hash_table( hm_t *row, const val_t h1, const exp_t * const ea, const hm_t * const b, const ht_t * const ht1, ht_t *ht2 ) { len_t j, l; exp_t *n; const len_t len = b[LENGTH]+OFFSET; const len_t evl = ht1->evl; exp_t * const *ev1 = ht1->ev; const hd_t * const hd1 = ht1->hd; exp_t **ev2 = ht2->ev; l = OFFSET; for (; l < len; ++l) { const exp_t * const eb = ev1[b[l]]; n = ev2[ht2->eld]; for (j = 0; j < evl; ++j) { n[j] = (exp_t)(ea[j] + eb[j]); } #if PARALLEL_HASHING const val_t h = h1 + hd1[b[l]].val; row[l] = check_insert_in_hash_table(n, h, ht2); #else row[l] = insert_in_hash_table(n, ht2); #endif } } static inline void reinsert_in_hash_table( hm_t *row, exp_t * const *oev, ht_t *ht ) { hl_t i; hi_t k, pos; len_t j, l; exp_t *e; hd_t *d; val_t h; const len_t len = row[LENGTH]+OFFSET; const len_t evl = ht->evl; const hi_t hsz = ht->hsz; /* ht->hsz <= 2^32 => mod is always uint32_t */ const hi_t mod = (hi_t)(hsz - 1); l = OFFSET; letsgo: for (; l < len; ++l) { const exp_t * const n = oev[row[l]]; /* generate hash value */ h = 0; for (j = 0; j < evl; ++j) { h += ht->rn[j] * n[j]; } k = h; i = 0; restart: for (; i < hsz; ++i) { k = (hi_t)(k+i) & mod; const hi_t hm = ht->hmap[k]; if (!hm) { break; } if (ht->hd[hm].val != h) { continue; } const exp_t * const ehm = ht->ev[hm]; for (j = 0; j < evl-1; j += 2) { if (n[j] != ehm[j] || n[j+1] != ehm[j+1]) { i++; goto restart; } } if (n[evl-1] != ehm[evl-1]) { i++; goto restart; } row[l] = hm; l++; goto letsgo; } /* add element to hash table */ ht->hmap[k] = pos = (hi_t)ht->eld; e = ht->ev[ht->eld]; d = ht->hd + ht->eld; memcpy(e, n, (unsigned long)evl * sizeof(exp_t)); d->sdm = generate_short_divmask(e, ht); d->deg = e[0]; d->deg += ht->ebl > 0 ? e[ht->ebl] : 0; d->val = h; ht->eld++; row[l] = pos; } } void reset_hash_table_indices( ht_t *ht, const hi_t * const hcm, const len_t len ) { for (len_t i = 0; i < len; ++i) { ht->hd[hcm[i]].idx = 0; } } static void reset_hash_table( ht_t *ht, bs_t *bs, ps_t *psl, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); len_t i; hi_t k; exp_t *e; spair_t *ps = psl->p; exp_t **oev = ht->ev; const len_t evl = ht->evl; const hl_t esz = ht->esz; const bl_t bld = bs->ld; const len_t pld = psl->ld; ht->ev = calloc(esz, sizeof(exp_t *)); if (ht->ev == NULL) { fprintf(stderr, "Computation needs too much memory on this machine,\n"); fprintf(stderr, "cannot reset ht->ev, esz = %lu\n", (unsigned long)esz); fprintf(stderr, "segmentation fault will follow.\n"); } exp_t *tmp = (exp_t *)malloc( (unsigned long)evl * esz * sizeof(exp_t)); if (tmp == NULL) { fprintf(stderr, "Computation needs too much memory on this machine,\n"); fprintf(stderr, "resetting table failed, esz = %lu\n", (unsigned long)esz); fprintf(stderr, "segmentation fault will follow.\n"); } for (k = 0; k < esz; ++k) { ht->ev[k] = tmp + k*evl; } ht->eld = 1; memset(ht->hmap, 0, ht->hsz * sizeof(hi_t)); memset(ht->hd, 0, esz * sizeof(hd_t)); /* reinsert known elements */ for (i = 0; i < bld; ++i) { if (bs->red[i] < 2) { reinsert_in_hash_table(bs->hm[i], oev, ht); } } for (i = 0; i < pld; ++i) { e = oev[ps[i].lcm]; #if PARALLEL_HASHING ps[i].lcm = check_insert_in_hash_table(e, 0, ht); #else ps[i].lcm = insert_in_hash_table(e, ht); #endif } /* note: all memory is allocated as a big block, so it is * enough to free oev[0]. */ free(oev[0]); free(oev); /* timings */ ct1 = cputime(); rt1 = realtime(); st->rht_ctime += ct1 - ct0; st->rht_rtime += rt1 - rt0; } /* computes lcm of a and b from ht1 and inserts it in ht2 */ static inline hi_t get_lcm( const hi_t a, const hi_t b, const ht_t *ht1, ht_t *ht2 ) { len_t i; /* exponents of basis elements, thus from basis hash table */ const exp_t * const ea = ht1->ev[a]; const exp_t * const eb = ht1->ev[b]; exp_t etmp[ht1->evl]; const len_t evl = ht1->evl; const len_t ebl = ht1->ebl; /* set degree(s), if ebl == 0, i.e. we do not have an elimination block * order then the second for loop is just not executed and the third one * computes correctly the full degree of the lcm. */ for (i = 1; i < evl; ++i) { etmp[i] = ea[i] < eb[i] ? eb[i] : ea[i]; } /* reset degree entries */ etmp[0] = 0; etmp[ebl] = 0; for (i = 1; i < ebl; ++i) { etmp[0] += etmp[i]; } for (i = ebl+1; i < evl; ++i) { etmp[ebl] += etmp[i]; } /* printf("lcm -> "); * for (int ii = 0; ii < evl; ++ii) { * printf("%d ", etmp[ii]); * } * printf("\n"); */ #if PARALLEL_HASHING return check_insert_in_hash_table(etmp, 0, ht2); #else return insert_in_hash_table(etmp, ht2); #endif } static inline hm_t *poly_to_matrix_row( ht_t *sht, const ht_t *bht, const hm_t *poly ) { hm_t *row = (hm_t *)malloc((unsigned long)(poly[LENGTH]+OFFSET) * sizeof(hm_t)); row[COEFFS] = poly[COEFFS]; row[PRELOOP] = poly[PRELOOP]; row[LENGTH] = poly[LENGTH]; /* hash table product insertions appear only here: * we check for hash table enlargements first and then do the insertions * without further elargment checks there */ while (sht->eld+poly[LENGTH] >= sht->esz) { enlarge_hash_table(sht); } insert_poly_in_hash_table(row, poly, bht, sht); return row; } static inline hm_t *multiplied_poly_to_matrix_row( ht_t *sht, const ht_t *bht, const val_t hm, const exp_t * const em, const hm_t *poly ) { hm_t *row = (hm_t *)malloc((unsigned long)(poly[LENGTH]+OFFSET) * sizeof(hm_t)); row[COEFFS] = poly[COEFFS]; row[PRELOOP] = poly[PRELOOP]; row[LENGTH] = poly[LENGTH]; /* hash table product insertions appear only here: * we check for hash table enlargements first and then do the insertions * without further elargment checks there */ while (sht->eld+poly[LENGTH] >= sht->esz) { enlarge_hash_table(sht); } insert_multiplied_poly_in_hash_table(row, hm, em, poly, bht, sht); return row; } msolve-0.6.5/src/neogb/hash.h000066400000000000000000000033161456710632100160140ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef GB_HASH_H #define GB_HASH_H #include "data.h" /* we have three different hash tables: * 1. one hash table for elements in the basis (bht) * 2. one hash table for the spairs during the update process (uht) * 3. one hash table for the multiplied elements during symbolic * preprocessing (sht) */ /* The idea of the structure of the hash table is taken from an * implementation by Roman Pearce and Michael Monagan in Maple. */ void reset_hash_table_indices( ht_t *ht, const hi_t * const hcm, const len_t len ); ht_t *initialize_basis_hash_table( md_t *st ); ht_t *copy_hash_table( const ht_t *bht ); ht_t *initialize_secondary_hash_table( const ht_t * const ht, const md_t * const md ); void free_shared_hash_data( ht_t *ht ); void free_hash_table( ht_t **htp ); void full_free_hash_table( ht_t **htp ); void calculate_divmask( ht_t *ht ); #endif msolve-0.6.5/src/neogb/io.c000066400000000000000000001252171456710632100155000ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "io.h" /* See exponent vector description in data.h for more information. */ static inline void set_exponent_vector( exp_t *ev, const int32_t *iev, /* input exponent vectors */ const int32_t idx, const ht_t *ht, const md_t *st ) { len_t i; const len_t nv = ht->nv; const len_t ebl = ht->ebl; const len_t nev = st->nev; const len_t off = ebl - nev + 1; ev[0] = 0; ev[ebl] = 0; for (i = 0; i < nev; ++i) { ev[i+1] = (exp_t)(iev+(nv*idx))[i]; /* degree */ ev[0] += ev[i+1]; } for (i = nev; i < nv; ++i) { ev[i+off] = (exp_t)(iev+(nv*idx))[i]; /* degree */ ev[ebl] += ev[i+off]; } } /* note that depending on the input data we set the corresponding * function pointers for monomial resp. spair comparisons, taking * spairs by a given minimal property for symbolic preprocessing, etc. */ void sort_terms_ff_8( cf8_t **cfp, hm_t **hmp, ht_t *ht ) { cf8_t *cf = *cfp; hm_t *hm = *hmp; hm_t *hmo = hm+OFFSET; const len_t len = hm[LENGTH]; len_t i, j, k; hm_t tmphm = 0; cf8_t tmpcf = 0; /* generate array of pointers to hm entries */ hm_t *phm[len]; for (i = 0; i < len; ++i) { phm[i] = &hmo[i]; } /* sort pointers to hm entries -> getting permutations */ sort_r(phm, (unsigned long)len, sizeof(phm[0]), initial_gens_cmp, ht); /* sort cf and hm using permutations stored in phm */ for (i = 0; i < len; ++i) { if (i != phm[i]-hmo) { tmpcf = cf[i]; tmphm = hmo[i]; k = i; while (i != (j = phm[k]-hmo)) { cf[k] = cf[j]; hmo[k] = hmo[j]; phm[k] = &hmo[k]; k = j; } cf[k] = tmpcf; hmo[k] = tmphm; phm[k] = &hmo[k]; } } *cfp = cf; *hmp = hm; } void sort_terms_ff_16( cf16_t **cfp, hm_t **hmp, ht_t *ht ) { cf16_t *cf = *cfp; hm_t *hm = *hmp; hm_t *hmo = hm+OFFSET; const len_t len = hm[LENGTH]; len_t i, j, k; hm_t tmphm = 0; cf16_t tmpcf = 0; /* generate array of pointers to hm entries */ hm_t *phm[len]; for (i = 0; i < len; ++i) { phm[i] = &hmo[i]; } /* sort pointers to hm entries -> getting permutations */ sort_r(phm, (unsigned long)len, sizeof(phm[0]), initial_gens_cmp, ht); /* sort cf and hm using permutations stored in phm */ for (i = 0; i < len; ++i) { if (i != phm[i]-hmo) { tmpcf = cf[i]; tmphm = hmo[i]; k = i; while (i != (j = phm[k]-hmo)) { cf[k] = cf[j]; hmo[k] = hmo[j]; phm[k] = &hmo[k]; k = j; } cf[k] = tmpcf; hmo[k] = tmphm; phm[k] = &hmo[k]; } } *cfp = cf; *hmp = hm; } void sort_terms_ff_32( cf32_t **cfp, hm_t **hmp, ht_t *ht ) { cf32_t *cf = *cfp; hm_t *hm = *hmp; hm_t *hmo = hm+OFFSET; const len_t len = hm[LENGTH]; len_t i, j, k; hm_t tmphm = 0; cf32_t tmpcf = 0; /* generate array of pointers to hm entries */ hm_t *phm[len]; for (i = 0; i < len; ++i) { phm[i] = &hmo[i]; } /* sort pointers to hm entries -> getting permutations */ sort_r(phm, (unsigned long)len, sizeof(phm[0]), initial_gens_cmp, ht); /* sort cf and hm using permutations stored in phm */ for (i = 0; i < len; ++i) { if (i != phm[i]-hmo) { tmpcf = cf[i]; tmphm = hmo[i]; k = i; while (i != (j = phm[k]-hmo)) { cf[k] = cf[j]; hmo[k] = hmo[j]; phm[k] = &hmo[k]; k = j; } cf[k] = tmpcf; hmo[k] = tmphm; phm[k] = &hmo[k]; } } *cfp = cf; *hmp = hm; } void sort_terms_qq( mpz_t **cfp, hm_t **hmp, ht_t *ht ) { mpz_t *cf = *cfp; hm_t *hm = *hmp; hm_t *hmo = hm+OFFSET; const len_t len = hm[LENGTH]; len_t i, j, k; hm_t tmphm = 0; mpz_t tmpcf; mpz_init(tmpcf); /* generate array of pointers to hm entries */ hm_t *phm[len]; for (i = 0; i < len; ++i) { phm[i] = &hmo[i]; } /* sort pointers to hm entries -> getting permutations */ sort_r(phm, (unsigned long)len, sizeof(phm[0]), initial_gens_cmp, ht); /* sort cf and hm using permutations stored in phm */ for (i = 0; i < len; ++i) { if (i != phm[i]-hmo) { mpz_swap(tmpcf, cf[i]); tmphm = hmo[i]; k = i; while (i != (j = phm[k]-hmo)) { mpz_swap(cf[k], cf[j]); hmo[k] = hmo[j]; phm[k] = &hmo[k]; k = j; } mpz_swap(cf[k], tmpcf); hmo[k] = tmphm; phm[k] = &hmo[k]; } } *cfp = cf; *hmp = hm; } void import_input_data( bs_t *bs, md_t *st, const int32_t start, const int32_t stop, const int32_t *lens, const int32_t *exps, const void *vcfs, const int *invalid_gens ) { int32_t i, j; len_t k; hm_t *hm; len_t ctr = 0; /* ctr for valid input elements */ cf8_t *cf8 = NULL; cf16_t *cf16 = NULL; cf32_t *cf32 = NULL; mpz_t *cfq = NULL; int32_t *cfs_ff = NULL; mpz_t **cfs_qq = NULL; ht_t *ht = bs->ht; int32_t off = 0; /* offset in arrays */ int32_t init_off = 0; const len_t fc = st->fc; len_t ngens = stop - start; for (i = 0; i < start; ++i) { init_off += lens[i]; } /* check basis size first */ /* check_enlarge_basis(bs, ngens_input, st); */ check_enlarge_basis(bs, ngens, st); /* import monomials */ exp_t *e = ht->ev[0]; /* use as temporary storage */ off = init_off; for (i = start; i < stop; ++i) { if (invalid_gens == NULL || invalid_gens[i] == 0) { while (lens[i] >= ht->esz-ht->eld) { enlarge_hash_table(ht); e = ht->ev[0]; /* reset e if enlarging */ } hm = (hm_t *)malloc(((unsigned long)lens[i]+OFFSET) * sizeof(hm_t)); bs->hm[ctr] = hm; hm[COEFFS] = ctr; /* link to matcf entry */ hm[PRELOOP] = (lens[i] % UNROLL); /* offset */ hm[LENGTH] = lens[i]; /* length */ bs->red[ctr] = 0; for (j = off; j < off+lens[i]; ++j) { set_exponent_vector(e, exps, j, ht, st); hm[j-off+OFFSET] = insert_in_hash_table(e, ht); } ctr++; } off += lens[i]; } /* import coefficients */ off = init_off; ctr = 0; switch (st->ff_bits) { case 8: cfs_ff = (int32_t *)vcfs; for (i = start; i < stop; ++i) { if (invalid_gens == NULL || invalid_gens[i] == 0) { cf8 = (cf8_t *)malloc((unsigned long)(lens[i]) * sizeof(cf8_t)); bs->cf_8[ctr] = cf8; for (j = off; j < off+lens[i]; ++j) { /* make coefficient positive */ cfs_ff[j] += (cfs_ff[j] >> 31) & fc; cf8[j-off] = (cf8_t)(cfs_ff[j] % fc); } sort_terms_ff_8(&(bs->cf_8[ctr]), &(bs->hm[ctr]), ht); ctr++; } off += lens[i]; } break; case 16: cfs_ff = (int32_t *)vcfs; for (i = start; i < stop; ++i) { if (invalid_gens == NULL || invalid_gens[i] == 0) { cf16 = (cf16_t *)malloc((unsigned long)(lens[i]) * sizeof(cf16_t)); bs->cf_16[ctr] = cf16; for (j = off; j < off+lens[i]; ++j) { /* make coefficient positive */ cfs_ff[j] += (cfs_ff[j] >> 31) & fc; cf16[j-off] = (cf16_t)(cfs_ff[j] % fc); } sort_terms_ff_16(&(bs->cf_16[ctr]), &(bs->hm[ctr]), ht); ctr++; } off += lens[i]; } break; case 32: cfs_ff = (int32_t *)vcfs; for (i = start; i < stop; ++i) { if (invalid_gens == NULL || invalid_gens[i] == 0) { cf32 = (cf32_t *)malloc((unsigned long)(lens[i]) * sizeof(cf32_t)); bs->cf_32[ctr] = cf32; for (j = off; j < off+lens[i]; ++j) { /* make coefficient positive */ cfs_ff[j] += (cfs_ff[j] >> 31) & fc; cf32[j-off] = (cf32_t)(cfs_ff[j] % fc); } sort_terms_ff_32(&(bs->cf_32[ctr]), &(bs->hm[ctr]), ht); ctr++; } off += lens[i]; } break; case 0: cfs_qq = (mpz_t **)vcfs; mpz_t prod_den, mul; mpz_inits(prod_den, mul, NULL); for (i = start; i < stop; ++i) { if (invalid_gens == NULL || invalid_gens[i] == 0) { mpz_set_si(prod_den, 1); for (j = off; j < off+lens[i]; ++j) { /* printf("i %u | j %u\n", i, j); * gmp_printf("%Zd\n", *(cfs[2*j+1])); */ mpz_mul(prod_den, prod_den, *(cfs_qq[2*j+1])); } cfq = (mpz_t *)malloc((unsigned long)(lens[i]) * sizeof(mpz_t)); bs->cf_qq[ctr] = cfq; for (j = 0; j < lens[i]; ++j) { mpz_init(cfq[j]); } for (j = off; j < off+lens[i]; ++j) { mpz_divexact(mul, prod_den, *(cfs_qq[2*j+1])); mpz_mul(cfq[j-off], mul, *(cfs_qq[2*j])); } sort_terms_qq(&(bs->cf_qq[ctr]), &(bs->hm[ctr]), ht); ctr++; } off += lens[i]; } break; default: exit(1); } /* maybe some input elements are invalid, so reset ngens here */ ngens = ctr; /* set total degree of input polynomials */ deg_t deg = 0; if (st->nev) { for (i = 0; i < ngens; ++i) { hm = bs->hm[i]; deg = ht->hd[hm[OFFSET]].deg; k = hm[LENGTH] + OFFSET; for (j = OFFSET+1; j < k; ++j) { if (deg < ht->hd[hm[j]].deg) { deg = ht->hd[hm[j]].deg; st->homogeneous = 1; } } bs->hm[i][DEG] = deg; } } else { for (i = 0; i < ngens; ++i) { hm = bs->hm[i]; bs->hm[i][DEG] = ht->hd[hm[OFFSET]].deg; } } if (st->homogeneous == 0) { /* check if input system is homogeneous or not */ for (i = 0; i < ngens; ++i) { hm = bs->hm[i]; deg = ht->hd[hm[OFFSET]].deg; k = hm[LENGTH] + OFFSET; for (j = OFFSET+1; j < k; ++j) { if (deg != ht->hd[hm[j]].deg) { st->homogeneous = 0; goto done; } } } st->homogeneous = 1; } done: /* we have to reset the ld value once we have normalized the initial * elements in order to start update correctly */ bs->ld = st->ngens; } /* return zero generator if all input generators are invalid */ static void return_zero( int32_t *bload, int32_t **blen, int32_t **bexp, void **bcf, const int32_t nr_vars, const uint32_t field_char, void *(*mallocp) (size_t) ) { int32_t *len = (int32_t *)(*mallocp)( (unsigned long)1 * sizeof(int32_t)); len[0] = 1; int32_t *exp = (int32_t *)(*mallocp)( (unsigned long)1 * (unsigned long)(nr_vars) * sizeof(int32_t)); memset(exp, 0, (unsigned long)nr_vars * sizeof(int32_t)); if (field_char > 0) { int32_t *cf = (int32_t *)(*mallocp)( (unsigned long)1 * sizeof(int32_t)); cf[0] = 0; } else { fprintf(stderr, "We only support finite fields.\n"); } } static int64_t export_data( int32_t *bload, int32_t **blen, int32_t **bexp, void **bcf, void *(*mallocp) (size_t), const bs_t * const bs, const ht_t * const ht, const md_t * const md ) { len_t i, j, k; hm_t *dt; void *cf; mpz_t *tmp_cf_q; const len_t nv = ht->nv; const len_t evl = ht->evl; const len_t ebl = ht->ebl; const len_t lml = bs->lml; int64_t nterms = 0; /* # of terms in basis */ int64_t nelts = 0; /* # elemnts in basis */ for (i = 0; i < lml; ++i) { if (bs->hm[bs->lmps[i]] != NULL) { nterms += (int64_t)bs->hm[bs->lmps[i]][LENGTH]; } else { nterms++; /* allocate one term for 0 polynomial */ } } nelts = lml; if (nelts > (int64_t)(pow(2, 31))) { printf("Basis has more than 2^31 elements, cannot store it.\n"); return 0; } int32_t *len = (int32_t *)(*mallocp)( (unsigned long)(nelts) * sizeof(int32_t)); int32_t *exp = (int32_t *)(*mallocp)( (unsigned long)(nterms) * (unsigned long)(nv) * sizeof(int32_t)); if (md->ff_bits == 0) { cf = (mpz_t *)(*mallocp)( (unsigned long)(nterms) * sizeof(mpz_t)); } else { cf = (int32_t *)(*mallocp)( (unsigned long)(nterms) * sizeof(int32_t)); } /* counters for lengths, exponents and coefficients */ int64_t cl = 0, ce = 0, cc = 0; for (i = 0; i < lml; ++i) { const bl_t bi = bs->lmps[i]; /* polynomial is zero */ if (bs->hm[bi] == NULL) { if (md->ff_bits == 0) { mpz_init(((mpz_t *)cf+cc)[0]); } else { ((int32_t *)cf+cc)[0] = (int32_t)0; } for (k = 1; k < evl; ++k) { exp[ce++] = (int32_t)0; } cc += 1; len[cl] = 1; cl++; continue; } /* polynomial is nonzero */ len[cl] = bs->hm[bi][LENGTH]; switch (md->ff_bits) { case 8: for (j = 0; j < len[cl]; ++j) { ((int32_t *)cf+cc)[j] = (int32_t)bs->cf_8[bs->hm[bi][COEFFS]][j]; } break; case 16: for (j = 0; j < len[cl]; ++j) { ((int32_t *)cf+cc)[j] = (int32_t)bs->cf_16[bs->hm[bi][COEFFS]][j]; } break; case 32: for (j = 0; j < len[cl]; ++j) { ((int32_t *)cf+cc)[j] = (int32_t)bs->cf_32[bs->hm[bi][COEFFS]][j]; } break; case 0: tmp_cf_q = bs->cf_qq[bs->hm[bi][COEFFS]]; for (j = 0; j < len[cl]; ++j) { mpz_init_set(((mpz_t *)cf+cc)[j], tmp_cf_q[j]); } break; default: exit(1); } dt = bs->hm[bi] + OFFSET; for (j = 0; j < len[cl]; ++j) { for (k = 1; k < ebl; ++k) { exp[ce++] = (int32_t)ht->ev[dt[j]][k]; } for (k = ebl+1; k < evl; ++k) { exp[ce++] = (int32_t)ht->ev[dt[j]][k]; } } cc += len[cl]; cl++; } *bload = (int32_t)nelts; *blen = len; *bexp = exp; *bcf = (void *)cf; return nterms; } void set_ff_bits(md_t *st, int32_t fc){ if (fc == 0) { st->ff_bits = 0; } else { if (fc < pow(2,8)) { st->ff_bits = 8; } else { if (fc < pow(2,16)) { st->ff_bits = 16; } else { if (fc < pow(2,32)) { st->ff_bits = 32; } } } } } /* return 1 if validation was possible, zero otherwise */ int validate_input_data( int **invalid_gensp, const void *cfs, const int32_t *lens, uint32_t *field_charp, int32_t *mon_orderp, int32_t *elim_block_lenp, int32_t *nr_varsp, int32_t *nr_gensp, int32_t *nr_nfp, int32_t *ht_sizep, int32_t *nr_threadsp, int32_t *max_nr_pairsp, int32_t *reset_htp, int32_t *la_optionp, int32_t *use_signaturesp, int32_t *reduce_gbp, int32_t *info_levelp ) { /* biggest prime msovle can handle */ if (*field_charp > 4294967291) { fprintf(stderr, "Field characteristic not valid.\n"); return 0; } if (*nr_varsp < 0) { fprintf(stderr, "Number of variables not valid.\n"); return 0; } if (*nr_gensp < 1) { fprintf(stderr, "Number of generators not valid.\n"); return 0; } if (*nr_nfp < 0 || *nr_nfp >= *nr_gensp) { fprintf(stderr, "Number of normal forms not valid.\n"); return 0; } if (*mon_orderp < 0) { fprintf(stderr, "Fixes monomial order to DRL.\n"); *mon_orderp = 0; } if (*elim_block_lenp < 0) { fprintf(stderr, "Fixes elim block order length to 0.\n"); *elim_block_lenp = 0; } if (*ht_sizep < 0) { fprintf(stderr, "Fixes initial hash table size to 2^17.\n"); *ht_sizep = 17; } if (*nr_threadsp < 0) { fprintf(stderr, "Fixes number of threads to 1.\n"); *nr_threadsp = 1; } if (*max_nr_pairsp < 0) { fprintf(stderr, "Fixes maximal number of spairs chosen to all possible.\n"); *max_nr_pairsp = 0; } if (*la_optionp != 1 && *la_optionp != 2 && *la_optionp != 42 && *la_optionp != 44) { fprintf(stderr, "Fixes linear algebra option to exact sparse.\n"); *la_optionp = 2; } if (*use_signaturesp < 0 || *use_signaturesp > 3) { fprintf(stderr, "Usage of signature not valid, disabled.\n"); *use_signaturesp = 0; } if (*reduce_gbp < 0 || *reduce_gbp > 1) { fprintf(stderr, "Fixes reduction of GB to 0 (false).\n"); *reduce_gbp = 0; } if (*info_levelp < 0 || *info_levelp > 2) { fprintf(stderr, "Fixes info level to no output.\n"); *info_levelp = 0; } const int ngens = *nr_gensp; int *invalid_gens = (int *)calloc((unsigned long)ngens, sizeof(int)); int ctr = 0; long len = 0; if (*field_charp == 0) { mpz_t **cf = (mpz_t **)cfs; for (long i = 0; i < 2*len; ++i) { if (mpz_cmp_si(*(cf[0]), 0) == 0) { invalid_gens[i] = 1; ctr++; } } } else { int32_t *cf = (int32_t *)cfs; for (int i = 0; i < ngens; ++i) { for (int j = 0; j < lens[i]; ++j) { if (cf[j+len] == 0) { invalid_gens[i] = 1; ctr++; break; } } len += lens[i]; } } *invalid_gensp = invalid_gens; if (ctr == 0) { return 1; } *nr_gensp -= ctr; /* recheck number of generators, if the input was only (0) then * no more generators are left over. */ if (*nr_gensp < 1) { return -1; } return 1; } int32_t check_and_set_meta_data( md_t *st, const int32_t *lens, const int32_t *exps, const void *cfs, const int *invalid_gens, const uint32_t field_char, const int32_t mon_order, const int32_t elim_block_len, const int32_t nr_vars, const int32_t nr_gens, const int32_t nr_nf, const int32_t ht_size, const int32_t nr_threads, const int32_t max_nr_pairs, const int32_t reset_hash_table, const int32_t la_option, const int32_t use_signatures, const int32_t reduce_gb, const int32_t pbm_file, const int32_t info_level ) { if (nr_gens <= 0 || nr_nf < 0 || nr_vars <= 0 || field_char < 0 || use_signatures < 0 || lens == NULL || cfs == NULL || exps == NULL) { fprintf(stderr, "Problem with meta data [%d, %d, %d]\n", (lens==NULL),(cfs==NULL),(exps==NULL)); return 1; } long ctr = 0; for (int i = 0; i < nr_gens; ++i) { ctr += invalid_gens[i]; } /* number of generators given from input file */ st->ngens_input = nr_gens - nr_nf; /* number of generators from input which are invalid */ st->ngens_invalid = ctr; /* number of valid generators */ st->ngens = st->ngens_input - ctr; st->init_bs_sz = 2 * nr_gens; st->nvars = nr_vars; /* note: prime check should be done in julia */ st->fc = field_char; set_ff_bits(st, st->fc); st->use_signatures = use_signatures; /* monomial order */ if (mon_order != 0 && mon_order != 1) { st->mo = 0; } else { st->mo = mon_order; } /* elimination block order? If so, store the blocks length */ st->nev = elim_block_len >= 0 ? elim_block_len : 0; if (st->nev >= st->nvars) { printf("error: Too large elimination block.\n"); exit(1); } /* set hash table size */ st->init_hts = ht_size; if (st->init_hts <= 0) { st->init_hts = 12; } /* info level */ st->info_level = info_level >= 0 ? info_level : 0; if (st->info_level > 2) { st->info_level = 2; } /* generation of pbm files on the fly? */ st->gen_pbm_file = pbm_file > 0 ? 1 : 0; /* resetting basis hash table */ st->reset_ht = reset_hash_table > 0 ? reset_hash_table : 2147483647; /* 2^31-1 */; /* set number of threads */ if (nr_threads <= 0) { st->nthrds = 1; } else { st->nthrds = nr_threads; } if (max_nr_pairs <= 0) { st->mnsel = 2147483647; /* 2^31-1 */ } else { st->mnsel = max_nr_pairs; } /* set linear algebra option */ if (la_option <= 0) { st->laopt = 1; } else { st->laopt = la_option; } if (reduce_gb < 0 || reduce_gb > 1) { st->reduce_gb = 0; } else { st->reduce_gb = reduce_gb; } set_function_pointers(st); return 0; } void set_function_pointers( const md_t *st ) { /* todo: this needs to be generalized for different monomial orders */ if (st->nev > 0) { initial_input_cmp = initial_input_cmp_be; initial_gens_cmp = initial_gens_cmp_be; monomial_cmp = monomial_cmp_be; spair_cmp = spair_cmp_be; hcm_cmp = hcm_cmp_pivots_be; } else { switch (st->mo) { case 0: initial_input_cmp = initial_input_cmp_drl; initial_gens_cmp = initial_gens_cmp_drl; monomial_cmp = monomial_cmp_drl; spair_cmp = spair_cmp_drl; hcm_cmp = hcm_cmp_pivots_drl; break; case 1: initial_input_cmp = initial_input_cmp_lex; initial_gens_cmp = initial_gens_cmp_lex; monomial_cmp = monomial_cmp_lex; spair_cmp = spair_cmp_deglex; hcm_cmp = hcm_cmp_pivots_lex; break; default: initial_input_cmp = initial_input_cmp_drl; initial_gens_cmp = initial_gens_cmp_drl; monomial_cmp = monomial_cmp_drl; spair_cmp = spair_cmp_drl; hcm_cmp = hcm_cmp_pivots_drl; } } /* up to 17 bits we can use one modular operation for reducing a row. this works * for matrices with #rows <= 54 million */ switch (st->ff_bits) { case 0: switch (st->laopt) { case 1: linear_algebra = exact_sparse_linear_algebra_ab_first_qq; break; case 2: linear_algebra = exact_sparse_linear_algebra_qq; break; default: linear_algebra = exact_sparse_linear_algebra_qq; } interreduce_matrix_rows = interreduce_matrix_rows_qq; break; case 8: switch (st->laopt) { case 1: linear_algebra = exact_sparse_dense_linear_algebra_ff_8; break; case 2: linear_algebra = exact_sparse_linear_algebra_ff_8; break; case 42: linear_algebra = probabilistic_sparse_dense_linear_algebra_ff_8; break; case 43: linear_algebra = probabilistic_sparse_dense_linear_algebra_ff_8_2; break; case 44: linear_algebra = probabilistic_sparse_linear_algebra_ff_8; break; default: linear_algebra = exact_sparse_linear_algebra_ff_8; } exact_linear_algebra = exact_sparse_linear_algebra_ff_8; interreduce_matrix_rows = interreduce_matrix_rows_ff_8; normalize_initial_basis = normalize_initial_basis_ff_8; break; case 16: switch (st->laopt) { case 1: linear_algebra = exact_sparse_dense_linear_algebra_ff_16; break; case 2: linear_algebra = exact_sparse_linear_algebra_ff_16; break; case 42: linear_algebra = probabilistic_sparse_dense_linear_algebra_ff_16; break; case 43: linear_algebra = probabilistic_sparse_dense_linear_algebra_ff_16_2; break; case 44: linear_algebra = probabilistic_sparse_linear_algebra_ff_16; break; default: linear_algebra = exact_sparse_linear_algebra_ff_16; } exact_linear_algebra = exact_sparse_linear_algebra_ff_16; interreduce_matrix_rows = interreduce_matrix_rows_ff_16; normalize_initial_basis = normalize_initial_basis_ff_16; break; case 32: switch (st->laopt) { case 1: linear_algebra = exact_sparse_dense_linear_algebra_ff_32; break; case 2: linear_algebra = exact_sparse_linear_algebra_ff_32; break; case 42: linear_algebra = probabilistic_sparse_dense_linear_algebra_ff_32; break; case 43: linear_algebra = probabilistic_sparse_dense_linear_algebra_ff_32_2; break; case 44: linear_algebra = probabilistic_sparse_linear_algebra_ff_32; break; default: linear_algebra = exact_sparse_linear_algebra_ff_32; } exact_linear_algebra = exact_sparse_linear_algebra_ff_32; interreduce_matrix_rows = interreduce_matrix_rows_ff_32; normalize_initial_basis = normalize_initial_basis_ff_32; sba_linear_algebra = sba_linear_algebra_ff_32; sba_reduce_dense_row_by_known_pivots_sparse_ff_32 = sba_reduce_dense_row_by_known_pivots_sparse_31_bit; /* if coeffs are smaller than 17 bit we can optimize reductions */ if (st->fc < pow(2, 18)) { reduce_dense_row_by_all_pivots_ff_32 = reduce_dense_row_by_all_pivots_17_bit; reduce_dense_row_by_old_pivots_ff_32 = reduce_dense_row_by_old_pivots_17_bit; reduce_dense_row_by_known_pivots_sparse_ff_32 = reduce_dense_row_by_known_pivots_sparse_17_bit; reduce_dense_row_by_dense_new_pivots_ff_32 = reduce_dense_row_by_dense_new_pivots_17_bit; } else { if (st->fc < pow(2, 31)) { reduce_dense_row_by_all_pivots_ff_32 = reduce_dense_row_by_all_pivots_31_bit; reduce_dense_row_by_old_pivots_ff_32 = reduce_dense_row_by_old_pivots_31_bit; reduce_dense_row_by_known_pivots_sparse_ff_32 = reduce_dense_row_by_known_pivots_sparse_31_bit; reduce_dense_row_by_dense_new_pivots_ff_32 = reduce_dense_row_by_dense_new_pivots_31_bit; } else { reduce_dense_row_by_all_pivots_ff_32 = reduce_dense_row_by_all_pivots_31_bit; reduce_dense_row_by_old_pivots_ff_32 = reduce_dense_row_by_old_pivots_31_bit; reduce_dense_row_by_known_pivots_sparse_ff_32 = reduce_dense_row_by_known_pivots_sparse_32_bit; reduce_dense_row_by_dense_new_pivots_ff_32 = reduce_dense_row_by_dense_new_pivots_31_bit; } } break; default: switch (st->laopt) { case 1: linear_algebra = exact_sparse_dense_linear_algebra_ff_32; break; case 2: linear_algebra = exact_sparse_linear_algebra_ff_32; break; case 42: linear_algebra = probabilistic_sparse_dense_linear_algebra_ff_32; break; case 43: linear_algebra = probabilistic_sparse_dense_linear_algebra_ff_32_2; break; case 44: linear_algebra = probabilistic_sparse_linear_algebra_ff_32; break; default: linear_algebra = exact_sparse_linear_algebra_ff_32; } exact_linear_algebra = exact_sparse_linear_algebra_ff_32; interreduce_matrix_rows = interreduce_matrix_rows_ff_32; normalize_initial_basis = normalize_initial_basis_ff_32; /* if coeffs are smaller than 17 bit we can optimize reductions */ if (st->fc < pow(2, 18)) { reduce_dense_row_by_all_pivots_ff_32 = reduce_dense_row_by_all_pivots_17_bit; reduce_dense_row_by_old_pivots_ff_32 = reduce_dense_row_by_old_pivots_17_bit; reduce_dense_row_by_known_pivots_sparse_ff_32 = reduce_dense_row_by_known_pivots_sparse_17_bit; reduce_dense_row_by_dense_new_pivots_ff_32 = reduce_dense_row_by_dense_new_pivots_17_bit; } else { if (st->fc < pow(2, 31)) { reduce_dense_row_by_all_pivots_ff_32 = reduce_dense_row_by_all_pivots_31_bit; reduce_dense_row_by_old_pivots_ff_32 = reduce_dense_row_by_old_pivots_31_bit; reduce_dense_row_by_known_pivots_sparse_ff_32 = reduce_dense_row_by_known_pivots_sparse_31_bit; reduce_dense_row_by_dense_new_pivots_ff_32 = reduce_dense_row_by_dense_new_pivots_31_bit; } else { reduce_dense_row_by_all_pivots_ff_32 = reduce_dense_row_by_all_pivots_31_bit; reduce_dense_row_by_old_pivots_ff_32 = reduce_dense_row_by_old_pivots_31_bit; reduce_dense_row_by_known_pivots_sparse_ff_32 = reduce_dense_row_by_known_pivots_sparse_32_bit; reduce_dense_row_by_dense_new_pivots_ff_32 = reduce_dense_row_by_dense_new_pivots_31_bit; } } } } int32_t check_and_set_meta_data_trace( md_t *st, const int32_t *lens, const int32_t *exps, const void *cfs, const int *invalid_gens, const uint32_t field_char, const int32_t mon_order, const int32_t elim_block_len, const int32_t nr_vars, const int32_t nr_gens, const int32_t nr_nf, const int32_t ht_size, const int32_t nr_threads, const int32_t max_nr_pairs, const int32_t reset_hash_table, const int32_t la_option, const int32_t use_signatures, const int32_t reduce_gb, const uint32_t prime_start, const int32_t nr_primes, const int32_t pbm_file, const int32_t info_level ) { st->prime_start = prime_start; if (st->prime_start <= 0) { st->prime_start = 32003; } st->nprimes = nr_primes; if (st->nprimes <= 0) { st->nprimes = 10; } return check_and_set_meta_data(st, lens, exps, cfs, invalid_gens, field_char, mon_order, elim_block_len, nr_vars, nr_gens, nr_nf, ht_size, nr_threads, max_nr_pairs, reset_hash_table, la_option, use_signatures, reduce_gb, pbm_file, info_level); } static inline void reset_function_pointers( const uint32_t prime, const uint32_t laopt ) { if (prime < pow(2,8)) { exact_linear_algebra = exact_sparse_linear_algebra_ff_8; interreduce_matrix_rows = interreduce_matrix_rows_ff_8; normalize_initial_basis = normalize_initial_basis_ff_8; switch (laopt) { case 1: linear_algebra = exact_sparse_dense_linear_algebra_ff_8; break; case 2: linear_algebra = exact_sparse_linear_algebra_ff_8; break; case 42: linear_algebra = probabilistic_sparse_dense_linear_algebra_ff_8; break; case 43: linear_algebra = probabilistic_sparse_dense_linear_algebra_ff_8_2; break; case 44: linear_algebra = probabilistic_sparse_linear_algebra_ff_8; break; default: linear_algebra = exact_sparse_linear_algebra_ff_8; } } else { if (prime < pow(2,16)) { exact_linear_algebra = exact_sparse_linear_algebra_ff_16; interreduce_matrix_rows = interreduce_matrix_rows_ff_16; normalize_initial_basis = normalize_initial_basis_ff_16; switch (laopt) { case 1: linear_algebra = exact_sparse_dense_linear_algebra_ff_16; break; case 2: linear_algebra = exact_sparse_linear_algebra_ff_16; break; case 42: linear_algebra = probabilistic_sparse_dense_linear_algebra_ff_16; break; case 43: linear_algebra = probabilistic_sparse_dense_linear_algebra_ff_16_2; break; case 44: linear_algebra = probabilistic_sparse_linear_algebra_ff_16; break; default: linear_algebra = exact_sparse_linear_algebra_ff_16; } } else { exact_linear_algebra = exact_sparse_linear_algebra_ff_32; interreduce_matrix_rows = interreduce_matrix_rows_ff_32; normalize_initial_basis = normalize_initial_basis_ff_32; switch (laopt) { case 1: linear_algebra = exact_sparse_dense_linear_algebra_ff_32; break; case 2: linear_algebra = exact_sparse_linear_algebra_ff_32; break; case 42: linear_algebra = probabilistic_sparse_dense_linear_algebra_ff_32; break; case 43: linear_algebra = probabilistic_sparse_dense_linear_algebra_ff_32_2; break; case 44: linear_algebra = probabilistic_sparse_linear_algebra_ff_32; break; default: linear_algebra = exact_sparse_linear_algebra_ff_32; } if (prime < pow(2,18)) { reduce_dense_row_by_all_pivots_ff_32 = reduce_dense_row_by_all_pivots_17_bit; reduce_dense_row_by_old_pivots_ff_32 = reduce_dense_row_by_old_pivots_17_bit; reduce_dense_row_by_known_pivots_sparse_ff_32 = reduce_dense_row_by_known_pivots_sparse_17_bit; reduce_dense_row_by_dense_new_pivots_ff_32 = reduce_dense_row_by_dense_new_pivots_17_bit; } else { if (prime < pow(2,31)) { reduce_dense_row_by_all_pivots_ff_32 = reduce_dense_row_by_all_pivots_31_bit; reduce_dense_row_by_old_pivots_ff_32 = reduce_dense_row_by_old_pivots_31_bit; reduce_dense_row_by_known_pivots_sparse_ff_32 = reduce_dense_row_by_known_pivots_sparse_31_bit; reduce_dense_row_by_dense_new_pivots_ff_32 = reduce_dense_row_by_dense_new_pivots_31_bit; } else { reduce_dense_row_by_all_pivots_ff_32 = reduce_dense_row_by_all_pivots_31_bit; reduce_dense_row_by_old_pivots_ff_32 = reduce_dense_row_by_old_pivots_31_bit; reduce_dense_row_by_known_pivots_sparse_ff_32 = reduce_dense_row_by_known_pivots_sparse_32_bit; reduce_dense_row_by_dense_new_pivots_ff_32 = reduce_dense_row_by_dense_new_pivots_31_bit; } } } } } static inline void reset_trace_function_pointers( const uint32_t prime ) { if (prime < pow(2,8)) { exact_linear_algebra = exact_sparse_linear_algebra_ff_8; interreduce_matrix_rows = interreduce_matrix_rows_ff_8; normalize_initial_basis = normalize_initial_basis_ff_8; application_linear_algebra = exact_application_sparse_linear_algebra_ff_8; trace_linear_algebra = exact_trace_sparse_linear_algebra_ff_8; } else { if (prime < pow(2,16)) { exact_linear_algebra = exact_sparse_linear_algebra_ff_16; interreduce_matrix_rows = interreduce_matrix_rows_ff_16; normalize_initial_basis = normalize_initial_basis_ff_16; application_linear_algebra = exact_application_sparse_linear_algebra_ff_16; trace_linear_algebra = exact_trace_sparse_linear_algebra_ff_16; } else { exact_linear_algebra = exact_sparse_linear_algebra_ff_32; interreduce_matrix_rows = interreduce_matrix_rows_ff_32; normalize_initial_basis = normalize_initial_basis_ff_32; application_linear_algebra = exact_application_sparse_linear_algebra_ff_32; trace_linear_algebra = exact_trace_sparse_linear_algebra_ff_32; if (prime < pow(2,18)) { reduce_dense_row_by_all_pivots_ff_32 = reduce_dense_row_by_all_pivots_17_bit; reduce_dense_row_by_old_pivots_ff_32 = reduce_dense_row_by_old_pivots_17_bit; trace_reduce_dense_row_by_known_pivots_sparse_ff_32 = trace_reduce_dense_row_by_known_pivots_sparse_17_bit; reduce_dense_row_by_known_pivots_sparse_ff_32 = reduce_dense_row_by_known_pivots_sparse_17_bit; reduce_dense_row_by_dense_new_pivots_ff_32 = reduce_dense_row_by_dense_new_pivots_17_bit; } else { if (prime < pow(2,31)) { reduce_dense_row_by_all_pivots_ff_32 = reduce_dense_row_by_all_pivots_31_bit; reduce_dense_row_by_old_pivots_ff_32 = reduce_dense_row_by_old_pivots_31_bit; trace_reduce_dense_row_by_known_pivots_sparse_ff_32 = trace_reduce_dense_row_by_known_pivots_sparse_31_bit; reduce_dense_row_by_known_pivots_sparse_ff_32 = reduce_dense_row_by_known_pivots_sparse_31_bit; reduce_dense_row_by_dense_new_pivots_ff_32 = reduce_dense_row_by_dense_new_pivots_31_bit; } else { reduce_dense_row_by_all_pivots_ff_32 = reduce_dense_row_by_all_pivots_31_bit; reduce_dense_row_by_old_pivots_ff_32 = reduce_dense_row_by_old_pivots_31_bit; trace_reduce_dense_row_by_known_pivots_sparse_ff_32 = trace_reduce_dense_row_by_known_pivots_sparse_32_bit; reduce_dense_row_by_known_pivots_sparse_ff_32 = reduce_dense_row_by_known_pivots_sparse_32_bit; reduce_dense_row_by_dense_new_pivots_ff_32 = reduce_dense_row_by_dense_new_pivots_31_bit; } } } } } static void write_pbm_file( mat_t *mat, const md_t * const st ) { len_t i, j, k; unsigned char b = 0; char buffer[512]; char fn[200]; hm_t **rows = mat->rr; const len_t ncols = mat->nc; const len_t nru = mat->nru; const len_t nrl = mat->nrl; snprintf(fn, 200, "%d-%d-%d-%d.pbm", st->current_rd, nru+nrl, ncols, st->current_deg); FILE *fh = fopen(fn, "wb"); /* magic header */ snprintf(buffer, 512, "P4\n# matrix size(%u, %u)\n%u %u\n", nru+nrl, ncols, ncols, nru+nrl); fwrite(buffer, sizeof(char), strlen(buffer), fh); for (i = 0; i < nru; ++i) { const len_t len = rows[i][LENGTH]; hm_t row[len]; memcpy(row, rows[i]+OFFSET, (unsigned long)len * sizeof(hm_t)); qsort(row, (unsigned long)len, sizeof(hm_t), pbm_cmp); /* the rows may not be sorted by column indices, thus we * have to go over them again and again and again */ k = 0; for (j = 0; j < ncols; ++j) { if (k < len && row[k] == j) { b |= (unsigned char)(1 << (7 - (j % 8))); k++; } else { b &= (unsigned char) ~(1 << (7 - (j % 8))); } /* write each byte */ if (j % 8 == 7) { fwrite(&b, sizeof(unsigned char), 1, fh); b = 0; } } /* write leftover bits */ if (j % 8 != 0) { fwrite(&b, sizeof(unsigned char), 1, fh); } fflush(fh); } rows = mat->tr; for (i = 0; i < nrl; ++i) { const len_t len = rows[i][LENGTH]; hm_t row[len]; memcpy(row, rows[i]+OFFSET, (unsigned long)len * sizeof(hm_t)); qsort(row, (unsigned long)len, sizeof(hm_t), pbm_cmp); /* the rows may not be sorted by column indices, thus we * have to go over them again and again and again */ k = 0; for (j = 0; j < ncols; ++j) { if (k < len && row[k] == j) { b |= (unsigned char)(1 << (7 - (j % 8))); k++; } else { b &= (unsigned char) ~(1 << (7 - (j % 8))); } /* write each byte */ if (j % 8 == 7) { fwrite(&b, sizeof(unsigned char), 1, fh); b = 0; } } /* write leftover bits */ if (j % 8 != 0) { fwrite(&b, sizeof(unsigned char), 1, fh); } fflush(fh); } fclose(fh); } msolve-0.6.5/src/neogb/io.h000066400000000000000000000104621456710632100155000ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef GB_IO_H #define GB_IO_H #include "data.h" void set_function_pointers( const md_t *st ); void set_ff_bits(md_t *st, int32_t fc); void sort_terms_ff_8( cf8_t **cfp, hm_t **hmp, ht_t *ht ); void sort_terms_ff_16( cf16_t **cfp, hm_t **hmp, ht_t *ht ); void sort_terms_ff_32( cf32_t **cfp, hm_t **hmp, ht_t *ht ); void sort_terms_qq( mpz_t **cfp, hm_t **hmp, ht_t *ht ); void import_input_data( bs_t *bs, md_t *st, const int32_t start, const int32_t stop, const int32_t *lens, const int32_t *exps, const void *vcfs, const int *invalid_gens ); int32_t check_and_set_meta_data( md_t *st, const int32_t *lens, const int32_t *exps, const void *cfs, const int *invalid_gens, const uint32_t field_char, const int32_t mon_order, const int32_t elim_block_len, const int32_t nr_vars, const int32_t nr_gens, const int32_t nr_nf, const int32_t ht_size, const int32_t nr_threads, const int32_t max_nr_pairs, const int32_t reset_hash_table, const int32_t la_option, const int32_t use_signatures, const int32_t reduce_gb, const int32_t pbm_file, const int32_t info_level ); int32_t check_and_set_meta_data_trace( md_t *st, const int32_t *lens, const int32_t *exps, const void *cfs, const int *invalid_gens, const uint32_t field_char, const int32_t mon_order, const int32_t elim_block_len, const int32_t nr_vars, const int32_t nr_gens, const int32_t nr_nf, const int32_t ht_size, const int32_t nr_threads, const int32_t max_nr_pairs, const int32_t reset_hash_table, const int32_t la_option, const int32_t use_signatures, const int32_t reduce_gb, const uint32_t prime_start, const int32_t nr_primes, const int32_t pbm_file, const int32_t info_level ); /* for normal form input data */ void import_input_data_nf_ff_32( bs_t *tbr, ht_t *ht, md_t *st, const int32_t start, const int32_t stop, const int32_t *lens, const int32_t *exps, const void *vcfs ); void import_input_data_nf_ff_16( bs_t *tbr, ht_t *ht, md_t *st, const int32_t start, const int32_t stop, const int32_t *lens, const int32_t *exps, const void *vcfs ); void import_input_data_nf_qq( bs_t *tbr, ht_t *ht, md_t *st, const int32_t start, const int32_t stop, const int32_t *lens, const int32_t *exps, const void *vcfs ); int validate_input_data( int **invalid_gensp, const void *cfs, const int32_t *lens, uint32_t *field_charp, int32_t *mon_orderp, int32_t *elim_block_lenp, int32_t *nr_varsp, int32_t *nr_gensp, int32_t *nr_nfp, int32_t *ht_sizep, int32_t *nr_threadsp, int32_t *max_nr_pairsp, int32_t *reset_htp, int32_t *la_optionp, int32_t *use_signaturesp, int32_t *reduce_gbp, int32_t *info_levelp ); #endif msolve-0.6.5/src/neogb/la.h000066400000000000000000001212731456710632100154700ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef GB_LA_H #define GB_LA_H #include #include #include #include #ifdef _OPENMP #include #endif #include "config.h" #include "types.h" #if 0 static inline void copy_first_row_from_dense(mat_gb_block_t *bl, const mat_gb_block_t *obl, const mat_gb_meta_data_t *meta) { nelts_t i; bl->len[0] = 0; bl->len[1] = bl->len[0]; for (i=0; ibs; ++i) { if (obl->val[i] != 0) { bl->pos[bl->len[1]] = (bs_t)i; bl->val[bl->len[1]] = obl->val[i]; bl->len[1]++; } } } static inline void copy_first_row_from_sparse(mat_gb_block_t *bl, const mat_gb_block_t *obl) { bl->len[0] = obl->len[0]; bl->len[1] = obl->len[1]; memcpy(bl->pos, obl->pos, (bl->len[1]-bl->len[0]) * sizeof(bs_t)); memcpy(bl->val, obl->val, (bl->len[1]-bl->len[0]) * sizeof(cf_t)); } static inline void load_dense_row_for_update_from_dense(bf_t *dr, const nelts_t idx, const mat_gb_block_t *bl, const mat_gb_meta_data_t *meta) { nelts_t i; memset(dr, 0, meta->bs * sizeof(bf_t)); for (i=0; ibs; ++i) dr[i] = (bf_t)bl->val[idx*meta->bs+i]; } static inline void load_dense_block_from_sparse(bf_t *db, const mat_gb_block_t *bl, const mat_gb_meta_data_t *meta) { nelts_t i, j; memset(db, 0, (meta->bs*meta->bs) * sizeof(bf_t)); if (bl->len != NULL) { for (i=0; inr; ++i) { for (j=bl->len[i]; jlen[i+1]; ++j) { db[i*meta->bs + bl->pos[j]] = (bf_t)bl->val[j]; } } } } static inline void load_dense_block_for_update_full(bf_t *db, const mat_gb_block_t *bl, const mat_gb_meta_data_t *meta) { nelts_t i, j; memset(db, 0, meta->bs * meta->bs *sizeof(bf_t)); if (bl->len != NULL) { for (i = 0; i < bl->nr; ++i) { for (j=bl->len[i]; jlen[i+1]; ++j) { db[bl->pos[j] + i*meta->bs] = (bf_t)bl->val[j]; } } } else { if (bl->val == NULL) return; for (i = 0; i < bl->nr; ++i) { for (j=0; jbs; ++j) { db[j + i*meta->bs] = (bf_t)bl->val[j + i*meta->bs]; } } } } static inline void load_dense_block_for_update(bf_t *db, const mat_gb_block_t *bl, const mat_gb_meta_data_t *meta) { nelts_t i, j; memset(db, 0, meta->bs * bl->nr *sizeof(bf_t)); if (bl->len != NULL) { for (i = 0; i < bl->nr; ++i) { for (j=bl->len[i]; jlen[i+1]; ++j) { db[bl->pos[j] + i*meta->bs] = (bf_t)bl->val[j]; } } } else { for (i = 0; i < bl->nr; ++i) { for (j=0; jbs; ++j) { db[j + i*meta->bs] = (bf_t)bl->val[j + i*meta->bs]; } } } } static inline void load_dense_row_for_update(bf_t *dr, const nelts_t idx, const mat_gb_block_t *bl, const mat_gb_meta_data_t *meta) { nelts_t i; memset(dr, 0, meta->bs * sizeof(bf_t)); if (bl->len != NULL) { for (i=bl->len[idx]; ilen[idx+1]; ++i) dr[bl->pos[i]] = (bf_t)bl->val[i]; } else { if (bl->val != NULL) { for (i=0; ibs; ++i) dr[i] = (bf_t)bl->val[idx*meta->bs+i]; } } } static inline void load_dense_row_for_update_from_sparse(bf_t *dr, const nelts_t idx, const mat_gb_block_t *bl, const mat_gb_meta_data_t *meta) { nelts_t i; memset(dr, 0, meta->bs * sizeof(bf_t)); if (bl->len != NULL) { for (i=bl->len[idx]; ilen[idx+1]; ++i) dr[bl->pos[i]] = (bf_t)bl->val[i]; } } static inline void write_updated_block_to_sparse_format_directly(mat_gb_block_t *bl, const bf_t *db, const nelts_t lr, const mat_gb_meta_data_t *meta) { nelts_t i, j; bf_t tmp; free(bl->len); bl->len = (nelts_t *)calloc((meta->bs+1), sizeof(nelts_t)); bl->pos = realloc(bl->pos, meta->bs*meta->bs * sizeof(bs_t)); bl->val= realloc(bl->val, meta->bs*meta->bs * sizeof(cf_t)); for (i = 0; i < lr; ++i) { bl->len[i+1] = bl->len[i]; for (j = 0; j < meta->bs; ++j) { if (db[j + i*meta->bs] != 0) { tmp = db[j + i*meta->bs] % meta->mod; if (tmp != 0) { bl->pos[bl->len[i+1]] = (bs_t)j; bl->val[bl->len[i+1]] = (cf_t)tmp; bl->len[i+1]++; } } } } } static inline void write_updated_block_to_sparse_format(mat_gb_block_t *bl, const bf_t *db, const nelts_t lr, const mat_gb_meta_data_t *meta) { nelts_t i, j; bf_t tmp; for (i = 0; i < lr; ++i) { bl->len[i+1] = bl->len[i]; for (j = 0; j < meta->bs; ++j) { if (db[j + i*meta->bs] != 0) { tmp = db[j + i*meta->bs] % meta->mod; if (tmp != 0) { bl->pos[bl->len[i+1]] = (bs_t)j; bl->val[bl->len[i+1]] = (cf_t)tmp; bl->len[i+1]++; } } } } } static inline void write_updated_row_to_sparse_format(mat_gb_block_t *bl, const bf_t *dr, const nelts_t idx, const mat_gb_meta_data_t *meta) { nelts_t i; bf_t tmp; bl->len[idx+1] = bl->len[idx]; for (i=0; ibs; ++i) { if (dr[i] != 0) { tmp = dr[i] % meta->mod; if (tmp != 0) { bl->pos[bl->len[idx+1]] = (bs_t)i; bl->val[bl->len[idx+1]] = (cf_t)tmp; bl->len[idx+1]++; } } } } static inline void set_updated_block(mat_gb_block_t **bl, mat_gb_block_t* new_bl) { mat_gb_block_t *blin = *bl; free(blin->len); free(blin->pos); free(blin->val); blin->len = new_bl->len; blin->pos = new_bl->pos; blin->val = new_bl->val; free(new_bl); } static inline void update_dense_row_dense_rev_order_dense(bf_t *dr, const nelts_t idx, const mat_gb_block_t *bl, const mat_gb_block_t *mbl, const mat_gb_meta_data_t *meta) { nelts_t i, j; for (i=idx*meta->bs; i<(idx+1)*meta->bs; ++i) { if (mbl->val[i] != 0) { const bf_t mul = (bf_t)meta->mod - mbl->val[i]; const nelts_t ri = bl->nr -1 - (i - idx*meta->bs); const cf_t *red = bl->val+(ri*meta->bs); for (j=0; jbs; j=j+8) { dr[j] += mul * red[j]; dr[j+1] += mul * red[j+1]; dr[j+2] += mul * red[j+2]; dr[j+OFFSET] += mul * red[j+OFFSET]; dr[j+4] += mul * red[j+4]; dr[j+5] += mul * red[j+5]; dr[j+6] += mul * red[j+6]; dr[j+7] += mul * red[j+7]; } } } } static inline void update_dense_row_dense_rev_order_sparse(bf_t *dr, const nelts_t idx, const mat_gb_block_t *bl, const mat_gb_block_t *mbl, const mat_gb_meta_data_t *meta) { nelts_t i, j; i=mbl->len[idx]; if (mbl->len[idx+1] > 3) { for (; ilen[idx+1]-3; i=i+4) { const bf_t mul1 = (bf_t)meta->mod - mbl->val[i]; const bf_t mul2 = (bf_t)meta->mod - mbl->val[i+1]; const bf_t mul3 = (bf_t)meta->mod - mbl->val[i+2]; const bf_t mul4 = (bf_t)meta->mod - mbl->val[i+OFFSET]; const nelts_t ri1 = bl->nr -1 - mbl->pos[i]; const nelts_t ri2 = bl->nr -1 - mbl->pos[i+1]; const nelts_t ri3 = bl->nr -1 - mbl->pos[i+2]; const nelts_t ri4 = bl->nr -1 - mbl->pos[i+OFFSET]; const cf_t *red1 = bl->val+(ri1*meta->bs); const cf_t *red2 = bl->val+(ri2*meta->bs); const cf_t *red3 = bl->val+(ri3*meta->bs); const cf_t *red4 = bl->val+(ri4*meta->bs); for (j=0; jbs; j=j+8) { dr[j] += mul1 * red1[j] + mul2 * red2[j] + mul3 * red3[j] + mul4 * red4[j]; dr[j+1] += mul1 * red1[j+1] + mul2 * red2[j+1] + mul3 * red3[j+1] + mul4 * red4[j+1]; dr[j+2] += mul1 * red1[j+2] + mul2 * red2[j+2] + mul3 * red3[j+2] + mul4 * red4[j+2]; dr[j+OFFSET] += mul1 * red1[j+OFFSET] + mul2 * red2[j+OFFSET] + mul3 * red3[j+OFFSET] + mul4 * red4[j+OFFSET]; dr[j+4] += mul1 * red1[j+4] + mul2 * red2[j+4] + mul3 * red3[j+4] + mul4 * red4[j+4]; dr[j+5] += mul1 * red1[j+5] + mul2 * red2[j+5] + mul3 * red3[j+5] + mul4 * red4[j+5]; dr[j+6] += mul1 * red1[j+6] + mul2 * red2[j+6] + mul3 * red3[j+6] + mul4 * red4[j+6]; dr[j+7] += mul1 * red1[j+7] + mul2 * red2[j+7] + mul3 * red3[j+7] + mul4 * red4[j+7]; } } } for (; ilen[idx+1]; i=i+1) { const bf_t mul1 = (bf_t)meta->mod - mbl->val[i]; const nelts_t ri1 = bl->nr -1 - mbl->pos[i]; const cf_t *red1 = bl->val+(ri1*meta->bs); for (j=0; jbs; j=j+8) { dr[j] += mul1 * red1[j]; dr[j+1] += mul1 * red1[j+1]; dr[j+2] += mul1 * red1[j+2]; dr[j+OFFSET] += mul1 * red1[j+OFFSET]; dr[j+4] += mul1 * red1[j+4]; dr[j+5] += mul1 * red1[j+5]; dr[j+6] += mul1 * red1[j+6]; dr[j+7] += mul1 * red1[j+7]; } } } static inline void update_dense_row_dense(bf_t *dr, const nelts_t idx, const mat_gb_block_t *bl, const mat_gb_block_t *mbl, const mat_gb_meta_data_t *meta) { nelts_t i, j; /* printf("bl->val %p\n", bl->val); * for (nelts_t k=0; k< meta->bs; ++k) { * printf("%p -- ",bl->val+(k*meta->bs)); * for (nelts_t l=0; l< meta->bs; ++l) { * printf("%u ", bl->val[k*meta->bs+l]); * } * printf("\n"); * } * printf("\n"); */ /* printf("val %p, pos %p\n", mbl->val, mbl->pos); */ /* printf("idx %u\n", idx); * for (int ii=0; iibs; ++ii) * printf("%lu ",dr[ii]); * printf("\n"); */ i = mbl->len[idx]; /* printf("len[idx+1] %u\n", mbl->len[idx+1]); */ if (mbl->len[idx+1] > 3) { #if 1 /* printf("1\n"); */ for (; ilen[idx+1]-3; i=i+4) { const bf_t mul1 = (bf_t)meta->mod - mbl->val[i]; const nelts_t ri1 = mbl->pos[i]; const bf_t mul2 = (bf_t)meta->mod - mbl->val[i+1]; const nelts_t ri2 = mbl->pos[i+1]; const bf_t mul3 = (bf_t)meta->mod - mbl->val[i+2]; const nelts_t ri3 = mbl->pos[i+2]; const bf_t mul4 = (bf_t)meta->mod - mbl->val[i+OFFSET]; const nelts_t ri4 = mbl->pos[i+OFFSET]; /* const nelts_t ri = bl->nr -1 - mbl->pos[i]; */ const cf_t *red1 = bl->val+(ri1*meta->bs); const cf_t *red2 = bl->val+(ri2*meta->bs); const cf_t *red3 = bl->val+(ri3*meta->bs); const cf_t *red4 = bl->val+(ri4*meta->bs); /* printf("red %p\n",red); * printf("ROW INDEX %u = %u - %u\n", ri, bl->nr, mbl->pos[i]); * * printf("RED1: "); * for (j=0; jbs; j++) { * printf("%u ", red[j]); * } * printf("\n"); * printf("BS %u\n", meta->bs); */ for (j=0; jbs; j=j+8) { /* printf("j %u\n", j); * printf("dr %lu\n", dr[j]); * printf("mul %lu\n", mul); * printf("red %u\n", red[j]); */ dr[j] += mul1 * red1[j] + mul2 * red2[j] + mul3 * red3[j] + mul4 * red4[j]; dr[j+1] += mul1 * red1[j+1] + mul2 * red2[j+1] + mul3 * red3[j+1] + mul4 * red4[j+1]; dr[j+2] += mul1 * red1[j+2] + mul2 * red2[j+2] + mul3 * red3[j+2] + mul4 * red4[j+2]; dr[j+OFFSET] += mul1 * red1[j+OFFSET] + mul2 * red2[j+OFFSET] + mul3 * red3[j+OFFSET] + mul4 * red4[j+OFFSET]; dr[j+4] += mul1 * red1[j+4] + mul2 * red2[j+4] + mul3 * red3[j+4] + mul4 * red4[j+4]; dr[j+5] += mul1 * red1[j+5] + mul2 * red2[j+5] + mul3 * red3[j+5] + mul4 * red4[j+5]; dr[j+6] += mul1 * red1[j+6] + mul2 * red2[j+6] + mul3 * red3[j+6] + mul4 * red4[j+6]; dr[j+7] += mul1 * red1[j+7] + mul2 * red2[j+7] + mul3 * red3[j+7] + mul4 * red4[j+7]; /* printf("%lu\n", dr[bl->pos[j]]); */ } } } #endif for (; ilen[idx+1]; ++i) { const bf_t mul = (bf_t)meta->mod - mbl->val[i]; const nelts_t ri = mbl->pos[i]; /* const nelts_t ri = bl->nr -1 - mbl->pos[i]; */ const cf_t *red = bl->val+(ri*meta->bs); /* printf("red %p\n",red); * printf("ROW INDEX %u = %u - %u\n", ri, bl->nr, mbl->pos[i]); * * printf("RED1: "); * for (j=0; jbs; j++) { * printf("%u ", red[j]); * } * printf("\n"); * printf("BS %u\n", meta->bs); */ for (j=0; jbs; j=j+8) { /* printf("j %u\n", j); * printf("dr %lu\n", dr[j]); * printf("mul %lu\n", mul); * printf("red %u\n", red[j]); */ dr[j] += mul * red[j]; dr[j+1] += mul * red[j+1]; dr[j+2] += mul * red[j+2]; dr[j+OFFSET] += mul * red[j+OFFSET]; dr[j+4] += mul * red[j+4]; dr[j+5] += mul * red[j+5]; dr[j+6] += mul * red[j+6]; dr[j+7] += mul * red[j+7]; /* printf("%lu\n", dr[bl->pos[j]]); */ } /* printf("ri %u\n", ri); * for (int ii=0; iibs; ++ii) * printf("%lu ",dr[ii]); * printf("\n"); */ } } static inline void update_dense_block_sparse(bf_t *db, const mat_gb_block_t *bl, const mat_gb_block_t *mbl, const nelts_t max, const mat_gb_meta_data_t *meta) { nelts_t i, j, k; register bf_t mul; register nelts_t ri; register nelts_t shift; for (i=0; ilen[i]; jlen[i+1]; ++j) { mul = (uint32_t)meta->mod - mbl->val[j]; ri = mbl->pos[j]; shift = (bl->len[ri+1]-bl->len[ri]) % 8; for (k=bl->len[ri]; klen[ri]+shift; ++k) { /* for (k=bl->len[ri]; klen[ri+1]; ++k) { */ db[i*meta->bs + bl->pos[k]] += mul * bl->val[k]; } for (; klen[ri+1]; k=k+8) { db[i*meta->bs + bl->pos[k]] += mul * bl->val[k]; db[i*meta->bs + bl->pos[k+1]] += mul * bl->val[k+1]; db[i*meta->bs + bl->pos[k+2]] += mul * bl->val[k+2]; db[i*meta->bs + bl->pos[k+OFFSET]] += mul * bl->val[k+OFFSET]; db[i*meta->bs + bl->pos[k+4]] += mul * bl->val[k+4]; db[i*meta->bs + bl->pos[k+5]] += mul * bl->val[k+5]; db[i*meta->bs + bl->pos[k+6]] += mul * bl->val[k+6]; db[i*meta->bs + bl->pos[k+7]] += mul * bl->val[k+7]; } } } } static inline void update_dense_block_sparse_self(bf_t *db, mat_gb_block_t *bl, const mat_gb_block_t *mbl, const mat_gb_meta_data_t *meta) { nelts_t i, j, k; for (i=0; inr; ++i) { for (j=mbl->len[i]; jlen[i+1]; ++j) { const bf_t mul = (bf_t)meta->mod - mbl->val[j]; /* printf("mul %u\n", mul); */ const nelts_t ri = bl->nr -1 - mbl->pos[j]; const nelts_t shift = (bl->len[ri+1]-bl->len[ri]) % 4; /* printf("bl->len[ri] %u | bl->len[ri+1] %u | shift %u\n", * bl->len[ri], bl->len[ri+1], shift); */ for (k=bl->len[ri]; klen[ri]+shift; ++k) { db[i*meta->bs + bl->pos[k]] += mul * bl->val[k]; } for (; klen[ri+1]; k=k+4) { db[i*meta->bs + bl->pos[k]] += mul * bl->val[k]; db[i*meta->bs + bl->pos[k+1]] += mul * bl->val[k+1]; db[i*meta->bs + bl->pos[k+2]] += mul * bl->val[k+2]; db[i*meta->bs + bl->pos[k+OFFSET]] += mul * bl->val[k+OFFSET]; } } /* for (int ii=0; iibs; ++ii) * printf("%lu ",db[i*meta->bs+ii]); * printf("\n"); */ write_updated_row_to_sparse_format(bl, db+i*meta->bs, i, meta); } } static inline void update_dense_row_sparse_rev_order_dense(bf_t *dr, const nelts_t idx, const mat_gb_block_t *bl, const mat_gb_block_t *mbl, const mat_gb_meta_data_t *meta) { nelts_t i, j; for (i=idx*meta->bs; i<(idx+1)*meta->bs; ++i) { if (mbl->val[i] != 0) { const bf_t mul = (bf_t)meta->mod - mbl->val[i]; const nelts_t ri = bl->nr -1 - (i - idx*meta->bs); const nelts_t shift = (bl->len[ri+1]-bl->len[ri]) % 8; /* printf("ri %u | idx %u | shift %u | bl->nr %u | len[ri] %u | len[ri+1] %u\n", ri, idx, */ for (j=bl->len[ri]; jlen[ri]+shift; ++j) { dr[bl->pos[j]] += mul * bl->val[j]; } for (; jlen[ri+1]; j=j+8) { dr[bl->pos[j]] += mul * bl->val[j]; dr[bl->pos[j+1]] += mul * bl->val[j+1]; dr[bl->pos[j+2]] += mul * bl->val[j+2]; dr[bl->pos[j+OFFSET]] += mul * bl->val[j+OFFSET]; dr[bl->pos[j+4]] += mul * bl->val[j+4]; dr[bl->pos[j+5]] += mul * bl->val[j+5]; dr[bl->pos[j+6]] += mul * bl->val[j+6]; dr[bl->pos[j+7]] += mul * bl->val[j+7]; } } } } static inline void update_dense_row_sparse_rev_order_sparse(bf_t *dr, const nelts_t idx, const mat_gb_block_t *bl, const mat_gb_block_t *mbl, const mat_gb_meta_data_t *meta) { nelts_t i, j; for (i=mbl->len[idx]; ilen[idx+1]; ++i) { const bf_t mul = (bf_t)meta->mod - mbl->val[i]; const nelts_t ri = bl->nr -1 - mbl->pos[i]; const nelts_t shift = (bl->len[ri+1]-bl->len[ri]) % 8; for (j=bl->len[ri]; jlen[ri]+shift; ++j) { dr[bl->pos[j]] += mul * bl->val[j]; } for (; jlen[ri+1]; j=j+8) { dr[bl->pos[j]] += mul * bl->val[j]; dr[bl->pos[j+1]] += mul * bl->val[j+1]; dr[bl->pos[j+2]] += mul * bl->val[j+2]; dr[bl->pos[j+OFFSET]] += mul * bl->val[j+OFFSET]; dr[bl->pos[j+4]] += mul * bl->val[j+4]; dr[bl->pos[j+5]] += mul * bl->val[j+5]; dr[bl->pos[j+6]] += mul * bl->val[j+6]; dr[bl->pos[j+7]] += mul * bl->val[j+7]; } } } static inline void update_dense_row_sparse(bf_t *dr, const nelts_t idx, const mat_gb_block_t *bl, const mat_gb_block_t *mbl, const mat_gb_meta_data_t *meta) { nelts_t i, j; for (i=mbl->len[idx]; ilen[idx+1]; ++i) { const bf_t mul = (bf_t)meta->mod - mbl->val[i]; const nelts_t ri = mbl->pos[i]; const nelts_t shift = (bl->len[ri+1]-bl->len[ri]) % 16; j=bl->len[ri]; for (; jlen[ri]+shift; ++j) { dr[bl->pos[j]] += mul * bl->val[j]; } for (; jlen[ri+1]; j=j+16) { dr[bl->pos[j]] += mul * bl->val[j]; dr[bl->pos[j+1]] += mul * bl->val[j+1]; dr[bl->pos[j+2]] += mul * bl->val[j+2]; dr[bl->pos[j+OFFSET]] += mul * bl->val[j+OFFSET]; dr[bl->pos[j+4]] += mul * bl->val[j+4]; dr[bl->pos[j+5]] += mul * bl->val[j+5]; dr[bl->pos[j+6]] += mul * bl->val[j+6]; dr[bl->pos[j+7]] += mul * bl->val[j+7]; dr[bl->pos[j+8]] += mul * bl->val[j+8]; dr[bl->pos[j+9]] += mul * bl->val[j+9]; dr[bl->pos[j+10]] += mul * bl->val[j+10]; dr[bl->pos[j+11]] += mul * bl->val[j+11]; dr[bl->pos[j+12]] += mul * bl->val[j+12]; dr[bl->pos[j+13]] += mul * bl->val[j+13]; dr[bl->pos[j+14]] += mul * bl->val[j+14]; dr[bl->pos[j+15]] += mul * bl->val[j+15]; } } } static inline void update_single_block_dense_rev_order(mat_gb_block_t *mat, const nelts_t shift, const nelts_t idx, const mat_gb_meta_data_t *meta) { nelts_t i; /* first block used as lookup table for updates */ const mat_gb_block_t *fbl = mat+shift; /* block to be updated */ mat_gb_block_t *ubl = mat+idx; /* row to be updated in dense format */ bf_t *dr = (bf_t *)malloc(meta->bs * sizeof(bf_t)); mat_gb_block_t *nbl = generate_mat_gb_block(meta, ubl->nr); if (fbl->len != NULL) { for (i=0; inr; ++i) { /* load dense row to be updated */ load_dense_row_for_update_from_dense(dr, i, ubl, meta); /* find corresponding row and multiplier */ update_dense_row_sparse_rev_order_sparse(dr, i, nbl, fbl, meta); /* write updated row to new storage holders */ write_updated_row_to_sparse_format(nbl, dr, i, meta); } } else { for (i=0; inr; ++i) { /* load dense row to be updated */ load_dense_row_for_update_from_dense(dr, i, ubl, meta); /* find corresponding row and multiplier */ update_dense_row_sparse_rev_order_dense(dr, i, nbl, fbl, meta); /* write updated row to new storage holders */ write_updated_row_to_sparse_format(nbl, dr, i, meta); } } free(dr); set_updated_block(&ubl, nbl); } static inline void update_single_block_dense(mat_gb_block_t *mat, const nelts_t shift, const nelts_t idx, const mat_gb_meta_data_t *meta) { nelts_t i; /* first block used as lookup table for updates */ const mat_gb_block_t *fbl = mat+shift; /* block to be updated */ mat_gb_block_t *ubl = mat+idx; /* row to be updated in dense format */ bf_t *dr = (bf_t *)malloc(meta->bs * sizeof(bf_t)); mat_gb_block_t *nbl = generate_mat_gb_block(meta, ubl->nr); for (i=1; inr; ++i) { /* load dense row to be updated */ load_dense_row_for_update_from_dense(dr, i, ubl, meta); /* find corresponding row and multiplier */ update_dense_row_sparse(dr, i, nbl, fbl, meta); /* write updated row to new storage holders */ write_updated_row_to_sparse_format(nbl, dr, i, meta); } free(dr); set_updated_block(&ubl, nbl); } static inline void update_single_block_sparse_2(mat_gb_block_t *mat, const nelts_t shift, const nelts_t idx, const mat_gb_meta_data_t *meta) { /* first block used as lookup table for updates */ const mat_gb_block_t *fbl = mat+shift; /* block to be updated */ mat_gb_block_t *ubl = mat+idx; /* row to be updated in dense format */ bf_t *db = (bf_t *)malloc((meta->bs*meta->bs) * sizeof(bf_t)); load_dense_block_from_sparse(db, ubl, meta); mat_gb_block_t *nbl = generate_mat_gb_block(meta, ubl->nr); update_dense_block_sparse(db, nbl, fbl, ubl->nr, meta); free(db); set_updated_block(&ubl, nbl); } static inline void update_single_block_sparse_rev_order(mat_gb_block_t *mat, const nelts_t shift, const nelts_t idx, const mat_gb_meta_data_t *meta) { nelts_t i; /* first block used as lookup table for updates */ const mat_gb_block_t *fbl = mat+shift; /* block to be updated */ mat_gb_block_t *ubl = mat+idx; /* row to be updated in dense format */ bf_t *dr = (bf_t *)malloc(meta->bs * sizeof(bf_t)); mat_gb_block_t *nbl = generate_mat_gb_block(meta, ubl->nr); for (i=0; inr; ++i) { /* load dense row to be updated */ load_dense_row_for_update_from_sparse(dr, i, ubl, meta); /* find corresponding row and multiplier */ /* printf("UPDATE ROW %u\n", i); */ update_dense_row_sparse_rev_order_sparse(dr, i, nbl, fbl, meta); /* write updated row to new storage holders */ write_updated_row_to_sparse_format(nbl, dr, i, meta); } free(dr); set_updated_block(&ubl, nbl); } static inline void update_single_block_sparse(mat_gb_block_t *mat, const nelts_t shift, const nelts_t idx, const mat_gb_meta_data_t *meta) { nelts_t i; /* first block used as lookup table for updates */ const mat_gb_block_t *fbl = mat+shift; /* block to be updated */ mat_gb_block_t *ubl = mat+idx; /* row to be updated in dense format */ bf_t *dr = (bf_t *)malloc(meta->bs * sizeof(bf_t)); mat_gb_block_t *nbl = generate_mat_gb_block(meta, ubl->nr); for (i=0; inr; ++i) { /* load dense row to be updated */ load_dense_row_for_update_from_sparse(dr, i, ubl, meta); /* find corresponding row and multiplier */ /* printf("UPDATE ROW %u\n", i); */ update_dense_row_sparse(dr, i, nbl, fbl, meta); /* write updated row to new storage holders */ write_updated_row_to_sparse_format(nbl, dr, i, meta); } free(dr); set_updated_block(&ubl, nbl); } static inline void update_single_block_rev_order(mat_gb_block_t *mat, const nelts_t shift, const nelts_t idx, const mat_gb_meta_data_t *meta) { if (mat[idx].len != NULL) { update_single_block_sparse_rev_order(mat, shift, idx, meta); } else { if (mat[idx].val != NULL) update_single_block_dense_rev_order(mat, shift, idx, meta); else return; } } static inline void update_single_block(mat_gb_block_t *mat, const nelts_t shift, const nelts_t idx, const mat_gb_meta_data_t *meta) { if (mat[idx].len != NULL) { update_single_block_sparse(mat, shift, idx, meta); } else { if (mat[idx].val != NULL) update_single_block_dense(mat, shift, idx, meta); else return; } } static inline void update_upper_row_block(mat_gb_block_t *mat, const nelts_t shift, const mat_gb_meta_data_t *meta, const int t) { /* printf("mat %p\n", mat); * printf("ncb %u\n", meta->ncb); */ #pragma omp parallel num_threads(t) { #pragma omp single nowait { /* the first block is used for updated the remaining ones, * i.e. we start at block index i=shift+1 */ /* printf("shift %u +1 < %u ncb?\n", shift, meta->ncb); */ for (nelts_t i=meta->ncb_AC; incb; ++i) { #pragma omp task update_single_block_rev_order(mat, shift, i, meta); } } } /* check density of blocks */ /* adjust_block_row_types(mat, meta); */ adjust_block_row_types_including_dense_righthand(mat, meta); } static inline void update_block(mat_gb_block_t **bl, const bf_t *db, const mat_gb_meta_data_t *meta) { nelts_t i, j; const nelts_t bs_square = meta->bs * meta->bs; bf_t tmp; mat_gb_block_t *blin = *bl; blin->len = realloc(blin->len, (meta->bs+1) * sizeof(nelts_t)); blin->pos = realloc(blin->pos, bs_square * sizeof(bs_t)); blin->val = realloc(blin->val, bs_square * sizeof(cf_t)); blin->len[0] = 0; for (i=0; ibs; ++i) { blin->len[i+1] = blin->len[i]; for (j=0; jbs; ++j) { tmp = db[i*meta->bs+j] % meta->mod; if (tmp != 0) { blin->pos[blin->len[i+1]] = (bs_t)j; blin->val[blin->len[i+1]] = (cf_t)tmp; blin->len[i+1]++; } } } if (blin->len[meta->bs] == 0) { free(blin->len); blin->len = NULL; free(blin->pos); blin->pos = NULL; free(blin->val); blin->val = NULL; } else { blin->pos = realloc(blin->pos, blin->len[meta->bs] * sizeof(bs_t)); blin->val = realloc(blin->val, blin->len[meta->bs] * sizeof(cf_t)); } } static inline void sparse_update_lower_block_by_upper_block_2(mat_gb_block_t *l, const mat_gb_block_t *u, const nelts_t shift, const nelts_t rbi, const nelts_t cbi, const mat_gb_meta_data_t *meta) { /* first multiplier block used as lookup table for updates */ const mat_gb_block_t *mbl = l + rbi*meta->ncb+shift; /* block to be updated */ /* printf("rbi %u | cbi %u | ncb %u | nrb %u | shift %u\n", * rbi, cbi, meta->ncb, meta->nrb_CD, shift); */ mat_gb_block_t *ubl = l + rbi*meta->ncb+cbi; /* row to be updated in dense format */ bf_t *db = (bf_t *)malloc((meta->bs*meta->bs) * sizeof(bf_t)); load_dense_block_from_sparse(db, ubl, meta); update_dense_block_sparse(db, u+cbi, mbl, ubl->nr, meta); update_block(&ubl, db, meta); free(db); } static inline void update_upper_blocks(const mat_gb_block_t *mul, const mat_gb_block_t *red, mat_gb_block_t *ubl, const mat_gb_meta_data_t *meta) { nelts_t i; /* row to be updated in dense format */ bf_t *dr = (bf_t *)malloc(meta->bs * sizeof(bf_t)); mat_gb_block_t *nbl = generate_mat_gb_block(meta, ubl->nr); if (red->len != NULL) { for (i=0; inr; ++i) { /* load dense row to be updated */ load_dense_row_for_update(dr, i, ubl, meta); update_dense_row_sparse_rev_order_sparse(dr, i, red, mul, meta); /* write updated row to new storage holders */ write_updated_row_to_sparse_format(nbl, dr, i, meta); } } else { for (i=0; inr; ++i) { /* load dense row to be updated */ load_dense_row_for_update(dr, i, ubl, meta); update_dense_row_dense_rev_order_sparse(dr, i, red, mul, meta); /* write updated row to new storage holders */ write_updated_row_to_sparse_format(nbl, dr, i, meta); } } set_updated_block(&ubl, nbl); free(dr); } static inline void sparse_update_lower_block_by_upper_block_rev_order( mat_gb_block_t *l, const mat_gb_block_t *u, const nelts_t shift, const nelts_t rbi, const nelts_t cbi, const mat_gb_meta_data_t *meta) { nelts_t i; /* first multiplier block used as lookup table for updates */ const mat_gb_block_t *mbl = l + rbi*meta->ncb+shift; /* block to be updated */ mat_gb_block_t *ubl = l + rbi*meta->ncb+cbi; /* row to be updated in dense format */ bf_t *dr = (bf_t *)malloc(meta->bs * sizeof(bf_t)); mat_gb_block_t *nbl = generate_mat_gb_block(meta, ubl->nr); /* printf("cbi %u | rbi %u\n", cbi, rbi); */ for (i=0; inr; ++i) { /* load dense row to be updated */ load_dense_row_for_update(dr, i, ubl, meta); /* load_dense_row_for_update_from_sparse(dr, i, ubl, meta); */ /* find corresponding row and multiplier */ /* we know already that u[cbi] is not the empty block, * so it is either sparse or dense */ if (u[cbi].len != NULL) { update_dense_row_sparse_rev_order_sparse(dr, i, u+cbi, mbl, meta); } else { update_dense_row_dense_rev_order_sparse(dr, i, u+cbi, mbl, meta); } /* write updated row to new storage holders */ write_updated_row_to_sparse_format(nbl, dr, i, meta); } set_updated_block(&ubl, nbl); free(dr); } static inline void sparse_update_lower_block_by_upper_block_at_once(mat_gb_block_t *l, const mat_gb_block_t *u, const nelts_t shift, const nelts_t rbi, const nelts_t cbi, const mat_gb_meta_data_t *meta) { /* first multiplier block used as lookup table for updates */ const mat_gb_block_t *mbl = l + rbi*meta->ncb+shift; mat_gb_block_t *ubl = l + rbi*meta->ncb+cbi; /* row to be updated in dense format */ bf_t *db = (bf_t *)malloc(meta->bs * ubl->nr * sizeof(bf_t)); load_dense_block_for_update(db, ubl, meta); mat_gb_block_t *nbl = generate_mat_gb_block(meta, ubl->nr); /* printf("cbi %u | rbi %u\n", cbi, rbi); */ if (u[cbi].len != NULL) { /* printf("sparse\n"); */ update_dense_block_sparse(db, u+cbi, mbl, ubl->nr, meta); #if 0 } else { /* printf("dense\n"); */ update_dense_block_dense(db, u+cbi, mbl, ubl->nr, meta); #endif } /* write updated row to new storage holders */ write_updated_block_to_sparse_format(nbl, db, ubl->nr, meta); set_updated_block(&ubl, nbl); free(db); } static inline void sparse_update_lower_block_by_upper_block(mat_gb_block_t *l, const mat_gb_block_t *u, const nelts_t shift, const nelts_t rbi, const nelts_t cbi, const mat_gb_meta_data_t *meta) { nelts_t i; /* first multiplier block used as lookup table for updates */ const mat_gb_block_t *mbl = l + rbi*meta->ncb+shift; /* block to be updated */ mat_gb_block_t *ubl = l + rbi*meta->ncb+cbi; /* row to be updated in dense format */ bf_t *dr = (bf_t *)malloc(meta->bs * sizeof(bf_t)); mat_gb_block_t *nbl = generate_mat_gb_block(meta, ubl->nr); for (i=0; inr; ++i) { /* load dense row to be updated */ load_dense_row_for_update(dr, i, ubl, meta); /* load_dense_row_for_update_from_sparse(dr, i, ubl, meta); */ /* find corresponding row and multiplier */ /* we know already that u[cbi] is not the empty block, * so it is either sparse or dense */ update_dense_row_sparse(dr, i, u+cbi, mbl, meta); /* write updated row to new storage holders */ write_updated_row_to_sparse_format(nbl, dr, i, meta); } set_updated_block(&ubl, nbl); free(dr); } static inline void sparse_update_D_blocks_by_B_blocks( mat_gb_block_t *l, mat_gb_block_t **u, const nelts_t rbi, const nelts_t cbi, const mat_gb_meta_data_t *meta) { nelts_t i; for (i = meta->ncb_AC; i < meta->ncb; ++i) { if (u[cbi][i].val != NULL) { sparse_update_lower_block_by_upper_block_rev_order( l, u[cbi], cbi, rbi, i, meta); } } /* free multiplier block from C */ free_mat_gb_block(l + cbi + rbi*meta->ncb); adjust_block_row_types_including_dense_righthand(l + rbi*meta->ncb, meta); } static inline void compute_multiples_in_first_block_at_once(bf_t *db, const mat_gb_block_t *bl, const mat_gb_meta_data_t *meta) { nelts_t i, j, l; for (l = 0; l < meta->bs; ++l) { for (i=0; inr; ++i) { if (db[i+l*meta->bs] != 0) { db[i+l*meta->bs] = db[i+l*meta->bs] % meta->mod; if (db[i+l*meta->bs] != 0) { const bf_t mul = (bf_t)meta->mod - db[i+l*meta->bs]; const nelts_t ri = i; const nelts_t shift = (bl->len[ri+1]-bl->len[ri]-1) % 4; for (j=bl->len[ri]+1; jlen[ri]+shift+1; ++j) { db[bl->pos[j]+l*meta->bs] += mul * bl->val[j]; } for (; jlen[ri+1]; j=j+4) { db[bl->pos[j]+l*meta->bs] += mul * bl->val[j]; db[bl->pos[j+1]+l*meta->bs] += mul * bl->val[j+1]; db[bl->pos[j+2]+l*meta->bs] += mul * bl->val[j+2]; db[bl->pos[j+OFFSET]+l*meta->bs] += mul * bl->val[j+OFFSET]; } } } } } } static inline void compute_multiples_in_first_block(bf_t *dr, const mat_gb_block_t *bl, const mat_gb_meta_data_t *meta) { nelts_t i, j; for (i=0; inr; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % meta->mod; if (dr[i] != 0) { const bf_t mul = (bf_t)meta->mod - dr[i]; const nelts_t ri = i; const nelts_t shift = (bl->len[ri+1]-bl->len[ri]-1) % 4; for (j=bl->len[ri]+1; jlen[ri]+shift+1; ++j) { dr[bl->pos[j]] += mul * bl->val[j]; } for (; jlen[ri+1]; j=j+4) { dr[bl->pos[j]] += mul * bl->val[j]; dr[bl->pos[j+1]] += mul * bl->val[j+1]; dr[bl->pos[j+2]] += mul * bl->val[j+2]; dr[bl->pos[j+OFFSET]] += mul * bl->val[j+OFFSET]; } } } } } static inline void sparse_update_first_block_by_upper_block(mat_gb_block_t *l, const mat_gb_block_t *u, const nelts_t shift, const nelts_t rbi, const mat_gb_meta_data_t *meta) { nelts_t i; /* block to be updated */ mat_gb_block_t *ubl = l + rbi*meta->ncb+shift; /* row to be updated in dense format */ bf_t *dr = (bf_t *)malloc(meta->bs * sizeof(bf_t)); mat_gb_block_t *nbl = generate_mat_gb_block(meta, ubl->nr); for (i=0; inr; ++i) { /* load dense row to be updated */ load_dense_row_for_update(dr, i, ubl, meta); /* load_dense_row_for_update_from_sparse(dr, i, ubl, meta); */ /* find corresponding row and multiplier */ /* we know already that u[cbi] is not the empty block, * so it is either sparse or dense */ compute_multiples_in_first_block(dr, u+shift, meta); /* write updated row to new storage holders */ write_updated_row_to_sparse_format(nbl, dr, i, meta); } set_updated_block(&ubl, nbl); free(dr); } static inline void update_lower_by_upper_row_block_not_prereduced( mat_gb_block_t *l, const mat_gb_block_t *u, const nelts_t shift, const mat_gb_meta_data_t *meta, const int t) { #pragma omp parallel num_threads(t) { #pragma omp single nowait { /* the first block is used for updated the remaining ones, * i.e. we start at block index i=1 */ for (nelts_t i=0; inrb_CD; ++i) { /* need to look at the first block in each row in * order to decide which algorithm to be chosen */ if (l[i*meta->ncb+shift].val != NULL) { sparse_update_first_block_by_upper_block(l, u, shift, i, meta); for (nelts_t j=shift+1; jncb; ++j) { if (u[j].val != NULL) { /* reduce first block */ #pragma omp task { /* sparse_update_lower_block_by_upper_block_at_once(l, u, shift, i, j, meta); */ sparse_update_lower_block_by_upper_block(l, u, shift, i, j, meta); } } } #pragma omp taskwait free_mat_gb_block(l+i*meta->ncb+shift); adjust_block_row_types_including_dense_righthand(l+i*meta->ncb, meta); } } } } } static inline void reduce_upper_column_block(mat_gb_block_t **l, const nelts_t shift, const mat_gb_meta_data_t *meta, const int t) { #pragma omp parallel num_threads(t) { #pragma omp single nowait { /* we only have to reduce B */ for (nelts_t i=0; incb_AC; jncb; ++j) { if (l[shift][j].val != NULL) { #pragma omp task { update_upper_blocks(l[i]+shift, l[shift]+j, l[i]+j, meta); } } } #pragma omp taskwait free_mat_gb_block(l[i]+shift); adjust_block_row_types_including_dense_righthand(l[i], meta); /* adjust_block_row_types_including_dense(l[i], meta); */ } } } } } static inline void update_lower_by_unreduced_upper_row_block(mat_gb_block_t *l, const mat_gb_block_t *u, const mat_gb_meta_data_t *meta, const int t) { #pragma omp parallel num_threads(t) { #pragma omp single nowait { /* loop over row blocks in CD */ for (nelts_t i = 0; i < meta->nrb_CD; ++i) { #pragma omp task { /* allocate memory for a dense block: * always the block to be updated */ bf_t *db = (bf_t *)malloc(meta->bs * meta->bs * sizeof(bf_t)); /* multiply with all previously updated blocks from A multiplied by C */ for (nelts_t j = 0; j < meta->ncb_AC; ++j) { load_dense_block_for_update_full(db, l+j+i*meta->ncb, meta); for (nelts_t k = 0; k < j; ++k) { if (u[k*meta->ncb + j].val != NULL && l[k+i*meta->ncb].val != NULL) { update_dense_block_sparse(db, u + k*meta->ncb + j, l + i*meta->ncb + k, meta->bs, meta); } } /* finally update block computing needed multiples for updating D later on */ compute_multiples_in_first_block_at_once(db, u+j*meta->ncb + j, meta); write_updated_block_to_sparse_format_directly(l+j+i*meta->ncb, db, l[j+i*meta->ncb].nr, meta); } /* now update D */ for (nelts_t j = meta->ncb_AC; j < meta->ncb; ++j) { load_dense_block_for_update_full(db, l+j+i*meta->ncb, meta); for (nelts_t k = 0; k < meta->nrb_AB; ++k) { if (u[k*meta->ncb + j].val != NULL && l[k+i*meta->ncb].val != NULL) { update_dense_block_sparse(db, u + k*meta->ncb + j, l + i*meta->ncb + k, meta->bs, meta); } } write_updated_block_to_sparse_format_directly(l+j+i*meta->ncb, db, l[j+i*meta->ncb].nr, meta); } /* free_mat_gb_block(l + j + i * meta->ncb); */ adjust_block_row_types_including_dense_righthand(l + i * meta->ncb, meta); free(db); } #pragma omp taskwait } } } } static inline void update_lower_by_reduced_upper_row_block(mat_gb_block_t *l, mat_gb_block_t **u, const mat_gb_meta_data_t *meta, const int t) { #pragma omp parallel num_threads(t) { #pragma omp single nowait { for (nelts_t i = 0; i < meta->ncb_AC; ++i) { for (nelts_t j = 0; j < meta->nrb_CD; ++j) { if (l[i + j*meta->ncb].val != 0) { #pragma omp task { sparse_update_D_blocks_by_B_blocks(l, u, j, i, meta); } } } #pragma omp taskwait } } } } static inline void update_lower_by_upper_row_block(mat_gb_block_t *l, mat_gb_block_t *u, const nelts_t shift, const mat_gb_meta_data_t *meta, const int t) { #pragma omp parallel num_threads(t) { #pragma omp single nowait { /* the first block is used for updated the remaining ones, * i.e. we start at block index i=1 */ for (nelts_t j=shift+1; jncb; ++j) { if (u[j].val != NULL) { for (nelts_t i=0; inrb_CD; ++i) { /* need to look at the first block in each row in * order to decide which algorithm to be chosen */ if (l[i*meta->ncb+shift].val != NULL) { #pragma omp task { sparse_update_lower_block_by_upper_block(l, u, shift, i, j, meta); } } } } else { continue; } } } } /* remove the first block in each block row */ for (nelts_t i=0; inrb_CD; ++i) { free_mat_gb_block(l+i*meta->ncb+shift); } /* at the moment we only work with sparse blocks */ #if 1 #pragma omp parallel num_threads(t) { #pragma omp single nowait { for (nelts_t i=0; inrb_CD; ++i) { #pragma omp task { /* check density of blocks */ adjust_block_row_types(l+i*meta->ncb, meta); } } } } #endif } static inline void reduce_upper_part(mat_gb_block_t **mat, const mat_gb_meta_data_t *meta, const int t) { for (nelts_t j=0; jnrb_AB; ++j) { /* if first block is not already unit matrix block * we have to update the block row */ if (mat[meta->nrb_AB-1-j][meta->nrb_AB-1-j].val != NULL) { update_upper_row_block(mat[meta->nrb_AB-1-j], meta->nrb_AB-1-j, meta, t); } reduce_upper_column_block(mat, meta->nrb_AB-1-j, meta, t); } } #endif #endif msolve-0.6.5/src/neogb/la_ff_16.c000066400000000000000000002241741456710632100164500ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "data.h" /* That's also enough if AVX512 is avaialable on the system */ #if defined HAVE_AVX2 #include #elif defined __aarch64__ #include #endif static inline cf16_t *normalize_dense_matrix_row_ff_16( cf16_t *row, const hm_t len, const uint32_t fc ) { len_t i; int64_t tmp1, tmp2, tmp3, tmp4; const hm_t os = len % UNROLL; const uint16_t fc16 = (uint16_t)fc; const uint16_t inv = mod_p_inverse_16(row[0], fc16); for (i = 1; i < os; ++i) { tmp1 = ((int64_t)row[i] * inv) % fc16; tmp1 += (tmp1 >> 63) & fc16; row[i] = (cf16_t)tmp1; } /* we need to set i to os since os < 1 is possible */ for (i = os; i < len; i += UNROLL) { tmp1 = ((int64_t)row[i] * inv) % fc16; tmp2 = ((int64_t)row[i+1] * inv) % fc16; tmp3 = ((int64_t)row[i+2] * inv) % fc16; tmp4 = ((int64_t)row[i+3] * inv) % fc16; tmp1 += (tmp1 >> 63) & fc16; tmp2 += (tmp2 >> 63) & fc16; tmp3 += (tmp3 >> 63) & fc16; tmp4 += (tmp4 >> 63) & fc16; row[i] = (cf16_t)tmp1; row[i+1] = (cf16_t)tmp2; row[i+2] = (cf16_t)tmp3; row[i+3] = (cf16_t)tmp4; } row[0] = 1; return row; } static inline cf16_t *normalize_sparse_matrix_row_ff_16( cf16_t *row, const len_t os, const len_t len, const uint32_t fc ) { len_t i; const uint16_t fc16 = (uint16_t)fc; const uint16_t inv = mod_p_inverse_16(row[0], fc16); for (i = 0; i < os; ++i) { row[i] = (cf16_t)(((uint32_t)row[i] * inv) % fc16); } /* we need to set i to os since os < 1 is possible */ for (i = os; i < len; i += UNROLL) { row[i] = (cf16_t)(((uint32_t)row[i] * inv) % fc16); row[i+1] = (cf16_t)(((uint32_t)row[i+1] * inv) % fc16); row[i+2] = (cf16_t)(((uint32_t)row[i+2] * inv) % fc16); row[i+3] = (cf16_t)(((uint32_t)row[i+3] * inv) % fc16); } row[0] = 1; return row; } static hm_t *reduce_dense_row_by_known_pivots_sparse_ff_16( int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t * const * const pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const hm_t tmp_pos, /* position of new coeffs array in tmpcf */ const len_t mh, /* multiplier hash for tracing */ const len_t bi, /* basis index of generating element */ const len_t tr, /* trace data? */ const uint32_t fc ) { hi_t i, j, k; hm_t *dts; cf16_t *cfs; int64_t np = -1; const int64_t mod = (int64_t)fc; const len_t ncols = mat->nc; const len_t ncl = mat->ncl; cf16_t * const * const mcf = mat->cf_16; rba_t *rba; if (tr > 0) { rba = mat->rba[tmp_pos]; } else { rba = NULL; } #if defined HAVE_AVX512_F uint32_t mone32 = (uint32_t)0xFFFFFFFF; uint16_t mone16 = (uint16_t)0xFFFF; uint32_t mone16h = (uint32_t)0xFFFF0000; __m512i mask32 = _mm512_set1_epi64(mone32); __m512i mask16 = _mm512_set1_epi32(mone16); __m512i mask16h = _mm512_set1_epi32(mone16h); int64_t res[8] __attribute__((aligned(64))); __m512i redv, mulv, prodh, prodl, prod, drv, resv; #elif defined HAVE_AVX2 uint32_t mone32 = (uint32_t)0xFFFFFFFF; uint16_t mone16 = (uint16_t)0xFFFF; uint32_t mone16h = (uint32_t)0xFFFF0000; __m256i mask32 = _mm256_set1_epi64x(mone32); __m256i mask16 = _mm256_set1_epi32(mone16); __m256i mask16h = _mm256_set1_epi32(mone16h); int64_t res[4] __attribute__((aligned(32))); __m256i redv, mulv, prodh, prodl, prod, drv, resv; #elif defined __aarch64__ uint64_t tmp[2] __attribute__((aligned(32))); uint32x4_t prodv; uint16x8_t redv; uint64x2_t drv, resv; #endif k = 0; for (i = dpiv; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { np = i; } k++; continue; } /* found reducer row, get multiplier */ const uint32_t mul = (uint32_t)(fc - dr[i]); dts = pivs[i]; if (i < ncl) { /* set corresponding bit of reducer in reducer bit array */ if (tr > 0) { rba[i/32] |= 1U << (i % 32); } } cfs = mcf[dts[COEFFS]]; #if defined HAVE_AVX512_F const uint16_t mul16 = (uint16_t)(fc - dr[i]); mulv = _mm512_set1_epi16(mul16); const len_t len = dts[LENGTH]; const len_t os = len % 32; const hm_t * const ds = dts + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += 32) { redv = _mm512_loadu_si512((__m512i*)(cfs+j)); prodh = _mm512_mulhi_epu16(mulv, redv); prodl = _mm512_mullo_epi16(mulv, redv); prod = _mm512_xor_si512( _mm512_and_si512(prodh, mask16h), _mm512_srli_epi32(prodl, 16)); drv = _mm512_setr_epi64( dr[ds[j+1]], dr[ds[j+5]], dr[ds[j+9]], dr[ds[j+13]], dr[ds[j+17]], dr[ds[j+21]], dr[ds[j+25]], dr[ds[j+29]]); resv = _mm512_add_epi64(drv, _mm512_and_si512(prod, mask32)); _mm512_store_si512((__m512i*)(res),resv); dr[ds[j+1]] = res[0]; dr[ds[j+5]] = res[1]; dr[ds[j+9]] = res[2]; dr[ds[j+13]] = res[3]; dr[ds[j+17]] = res[4]; dr[ds[j+21]] = res[5]; dr[ds[j+25]] = res[6]; dr[ds[j+29]] = res[7]; drv = _mm512_setr_epi64( dr[ds[j+3]], dr[ds[j+7]], dr[ds[j+11]], dr[ds[j+15]], dr[ds[j+19]], dr[ds[j+23]], dr[ds[j+27]], dr[ds[j+31]]); resv = _mm512_add_epi64(drv, _mm512_srli_epi64(prod, 32)); _mm512_store_si512((__m512i*)(res),resv); dr[ds[j+3]] = res[0]; dr[ds[j+7]] = res[1]; dr[ds[j+11]] = res[2]; dr[ds[j+15]] = res[3]; dr[ds[j+19]] = res[4]; dr[ds[j+23]] = res[5]; dr[ds[j+27]] = res[6]; dr[ds[j+31]] = res[7]; prod = _mm512_xor_si512( _mm512_slli_epi32(prodh, 16), _mm512_and_si512(prodl, mask16)); drv = _mm512_setr_epi64( dr[ds[j+0]], dr[ds[j+4]], dr[ds[j+8]], dr[ds[j+12]], dr[ds[j+16]], dr[ds[j+20]], dr[ds[j+24]], dr[ds[j+28]]); resv = _mm512_add_epi64(drv, _mm512_and_si512(prod, mask32)); _mm512_store_si512((__m512i*)(res),resv); dr[ds[j+0]] = res[0]; dr[ds[j+4]] = res[1]; dr[ds[j+8]] = res[2]; dr[ds[j+12]] = res[3]; dr[ds[j+16]] = res[4]; dr[ds[j+20]] = res[5]; dr[ds[j+24]] = res[6]; dr[ds[j+28]] = res[7]; drv = _mm512_setr_epi64( dr[ds[j+2]], dr[ds[j+6]], dr[ds[j+10]], dr[ds[j+14]], dr[ds[j+18]], dr[ds[j+22]], dr[ds[j+26]], dr[ds[j+30]]); resv = _mm512_add_epi64(drv, _mm512_srli_epi64(prod, 32)); _mm512_store_si512((__m512i*)(res),resv); dr[ds[j+2]] = res[0]; dr[ds[j+6]] = res[1]; dr[ds[j+10]] = res[2]; dr[ds[j+14]] = res[3]; dr[ds[j+18]] = res[4]; dr[ds[j+22]] = res[5]; dr[ds[j+26]] = res[6]; dr[ds[j+30]] = res[7]; } #elif defined HAVE_AVX2 const uint16_t mul16 = (uint16_t)(fc - dr[i]); mulv = _mm256_set1_epi16(mul16); const len_t len = dts[LENGTH]; const len_t os = len % 16; const hm_t * const ds = dts + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += 16) { redv = _mm256_loadu_si256((__m256i*)(cfs+j)); prodh = _mm256_mulhi_epu16(mulv, redv); prodl = _mm256_mullo_epi16(mulv, redv); prod = _mm256_xor_si256( _mm256_and_si256(prodh, mask16h), _mm256_srli_epi32(prodl, 16)); drv = _mm256_setr_epi64x( dr[ds[j+1]], dr[ds[j+5]], dr[ds[j+9]], dr[ds[j+13]]); resv = _mm256_add_epi64(drv, _mm256_and_si256(prod, mask32)); _mm256_store_si256((__m256i*)(res),resv); dr[ds[j+1]] = res[0]; dr[ds[j+5]] = res[1]; dr[ds[j+9]] = res[2]; dr[ds[j+13]] = res[3]; drv = _mm256_setr_epi64x( dr[ds[j+3]], dr[ds[j+7]], dr[ds[j+11]], dr[ds[j+15]]); resv = _mm256_add_epi64(drv, _mm256_srli_epi64(prod, 32)); _mm256_store_si256((__m256i*)(res),resv); dr[ds[j+3]] = res[0]; dr[ds[j+7]] = res[1]; dr[ds[j+11]] = res[2]; dr[ds[j+15]] = res[3]; prod = _mm256_xor_si256( _mm256_slli_epi32(prodh, 16), _mm256_and_si256(prodl, mask16)); drv = _mm256_setr_epi64x( dr[ds[j+0]], dr[ds[j+4]], dr[ds[j+8]], dr[ds[j+12]]); resv = _mm256_add_epi64(drv, _mm256_and_si256(prod, mask32)); _mm256_store_si256((__m256i*)(res),resv); dr[ds[j+0]] = res[0]; dr[ds[j+4]] = res[1]; dr[ds[j+8]] = res[2]; dr[ds[j+12]] = res[3]; drv = _mm256_setr_epi64x( dr[ds[j+2]], dr[ds[j+6]], dr[ds[j+10]], dr[ds[j+14]]); resv = _mm256_add_epi64(drv, _mm256_srli_epi64(prod, 32)); _mm256_store_si256((__m256i*)(res),resv); dr[ds[j+2]] = res[0]; dr[ds[j+6]] = res[1]; dr[ds[j+10]] = res[2]; dr[ds[j+14]] = res[3]; } #elif defined __aarch64__ const len_t len = dts[LENGTH]; const len_t os = len % 8; const hm_t * const ds = dts + OFFSET; const cf16_t mul16 = (cf16_t)(mod - dr[i]); for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += 8) { tmp[0] = (uint64_t)dr[ds[j]]; tmp[1] = (uint64_t)dr[ds[j+1]]; drv = vld1q_u64(tmp); redv = vld1q_u16((cf16_t *)(cfs)+j); prodv = vmull_n_u16(vget_low_u16(redv), mul16); resv = vaddw_u32(drv, vget_low_u32(prodv)); vst1q_u64(tmp, resv); dr[ds[j]] = (int64_t)tmp[0]; dr[ds[j+1]] = (int64_t)tmp[1]; tmp[0] = (uint64_t)dr[ds[j+2]]; tmp[1] = (uint64_t)dr[ds[j+3]]; drv = vld1q_u64(tmp); resv = vaddw_u32(drv, vget_high_u32(prodv)); vst1q_u64(tmp, resv); dr[ds[j+2]] = (int64_t)tmp[0]; dr[ds[j+3]] = (int64_t)tmp[1]; tmp[0] = (uint64_t)dr[ds[j+4]]; tmp[1] = (uint64_t)dr[ds[j+5]]; drv = vld1q_u64(tmp); prodv = vmull_n_u16( vget_high_u16(redv), mul16); resv = vaddw_u32(drv, vget_low_u32(prodv)); vst1q_u64(tmp, resv); dr[ds[j+4]] = (int64_t)tmp[0]; dr[ds[j+5]] = (int64_t)tmp[1]; tmp[0] = (uint64_t)dr[ds[j+6]]; tmp[1] = (uint64_t)dr[ds[j+7]]; drv = vld1q_u64(tmp); resv = vaddw_u32(drv, vget_high_u32(prodv)); vst1q_u64(tmp, resv); dr[ds[j+6]] = (int64_t)tmp[0]; dr[ds[j+7]] = (int64_t)tmp[1]; } #else const len_t os = dts[PRELOOP]; const len_t len = dts[LENGTH]; const hm_t * const ds = dts + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] += mul * cfs[j]; dr[ds[j+1]] += mul * cfs[j+1]; dr[ds[j+2]] += mul * cfs[j+2]; dr[ds[j+3]] += mul * cfs[j+3]; } #endif dr[i] = 0; } if (k == 0) { return NULL; } hm_t *row = (hm_t *)malloc((unsigned long)(k+OFFSET) * sizeof(hm_t)); cf16_t *cf = (cf16_t *)malloc((unsigned long)(k) * sizeof(cf16_t)); j = 0; hm_t *rs = row + OFFSET; for (i = ncl; i < ncols; ++i) { if (dr[i] != 0) { rs[j] = (hm_t)i; cf[j] = (cf16_t)dr[i]; j++; } } row[COEFFS] = tmp_pos; row[PRELOOP] = j % UNROLL; row[LENGTH] = j; mat->cf_16[tmp_pos] = cf; return row; } static hm_t *trace_reduce_dense_row_by_known_pivots_sparse_ff_16( rba_t *rba, int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t * const * const pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const hm_t tmp_pos, /* position of new coeffs array in tmpcf */ const len_t mh, /* multiplier hash for tracing */ const len_t bi, /* basis index of generating element */ const uint32_t fc ) { hi_t i, j, k; hm_t *dts; cf16_t *cfs; int64_t np = -1; const int64_t mod = (int64_t)fc; const len_t ncols = mat->nc; const len_t ncl = mat->ncl; cf16_t * const * const mcf = mat->cf_16; k = 0; for (i = dpiv; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { np = i; } k++; continue; } /* found reducer row, get multiplier */ const uint32_t mul = (uint32_t)(fc - dr[i]); dts = pivs[i]; if (i < ncl) { cfs = bs->cf_16[dts[COEFFS]]; /* set corresponding bit of reducer in reducer bit array */ rba[i/32] |= 1U << (i % 32); } else { cfs = mcf[dts[COEFFS]]; } const len_t os = dts[PRELOOP]; const len_t len = dts[LENGTH]; const hm_t * const ds = dts + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] += mul * cfs[j]; dr[ds[j+1]] += mul * cfs[j+1]; dr[ds[j+2]] += mul * cfs[j+2]; dr[ds[j+3]] += mul * cfs[j+3]; } dr[i] = 0; } if (k == 0) { return NULL; } hm_t *row = (hm_t *)malloc((unsigned long)(k+OFFSET) * sizeof(hm_t)); cf16_t *cf = (cf16_t *)malloc((unsigned long)(k) * sizeof(cf16_t)); j = 0; hm_t *rs = row + OFFSET; for (i = ncl; i < ncols; ++i) { if (dr[i] != 0) { rs[j] = (hm_t)i; cf[j] = (cf16_t)dr[i]; j++; } } row[BINDEX] = bi; row[MULT] = mh; row[COEFFS] = tmp_pos; row[PRELOOP] = j % UNROLL; row[LENGTH] = j; mat->cf_16[tmp_pos] = cf; return row; } static cf16_t *reduce_dense_row_by_all_pivots_ff_16( int64_t *dr, mat_t *mat, const bs_t * const bs, len_t *pc, hm_t *const * const pivs, cf16_t *const * const dpivs, const uint32_t fc ) { hi_t i, j, k, l; const int64_t mod = (int64_t)fc; len_t np = -1; cf16_t *red; const len_t ncl = mat->ncl; const len_t ncols = mat->nc; /* step 1: reduce by sparse known pivots */ for (i = *pc; i < ncl; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { continue; } /* found reducer row, get multiplier */ const uint32_t mul = (uint32_t)(fc - dr[i]); const cf16_t *cfs = bs->cf_16[pivs[i][COEFFS]]; const len_t os = pivs[i][PRELOOP]; const len_t len = pivs[i][LENGTH]; const hm_t * const ds = pivs[i] + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] += mul * cfs[j]; dr[ds[j+1]] += mul * cfs[j+1]; dr[ds[j+2]] += mul * cfs[j+2]; dr[ds[j+3]] += mul * cfs[j+3]; } dr[i] = 0; } k = 0; /* step 2: reduce by new dense pivots */ for (i = ncl; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (dpivs[i-ncl] == NULL) { if (np == -1) { np = i; } k++; continue; } red = dpivs[i-ncl]; const uint32_t mul = (uint32_t)(fc - dr[i]); const len_t os = (ncols - i) % UNROLL; for (l = 0, j = i; l < os; ++l, ++j) { dr[j] += mul * red[l]; } for (; j < ncols; l += UNROLL, j += UNROLL) { dr[j] += mul * red[l]; dr[j+1] += mul * red[l+1]; dr[j+2] += mul * red[l+2]; dr[j+3] += mul * red[l+3]; } } if (k == 0) { *pc = -1; return NULL; } cf16_t *row = (cf16_t *)calloc((unsigned long)(ncols-np), sizeof(cf16_t)); for (i = np; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } row[i-np] = (cf16_t)dr[i]; } if (row[0] != 1) { row = normalize_dense_matrix_row_ff_16(row, ncols-np, fc); } *pc = np - ncl; return row; } static cf16_t *reduce_dense_row_by_old_pivots_ff_16( int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t *const * const pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const uint32_t fc ) { hi_t i, j; const int64_t mod = (int64_t)fc; const len_t ncols = mat->nc; const len_t ncl = mat->ncl; const len_t ncr = mat->ncr; for (i = dpiv; i < ncl; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { continue; } /* found reducer row, get multiplier */ const uint32_t mul = (uint32_t)(fc - dr[i]); const cf16_t *cfs = bs->cf_16[pivs[i][COEFFS]]; const len_t os = pivs[i][PRELOOP]; const len_t len = pivs[i][LENGTH]; const hm_t * const ds = pivs[i] + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] += mul * cfs[j]; dr[ds[j+1]] += mul * cfs[j+1]; dr[ds[j+2]] += mul * cfs[j+2]; dr[ds[j+3]] += mul * cfs[j+3]; } dr[i] = 0; } /* store a dense row for further dense gaussian elimination */ cf16_t *row = (cf16_t *)calloc( (unsigned long)(ncr), sizeof(cf16_t)); j = 0; for (i = ncl; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; if (dr[i] != 0) { j++; row[i-ncl] = (cf16_t)dr[i]; } } } if (j == 0) { free(row); row = NULL; } return row; } static cf16_t *reduce_dense_row_by_dense_new_pivots_ff_16( int64_t *dr, len_t *pc, cf16_t * const * const pivs, const len_t ncr, const uint32_t fc ) { hi_t i, j, k, l; len_t np = -1; const int64_t mod = (int64_t)fc; for (k = 0, i = *pc; i < ncr; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { np = i; } k++; continue; } const uint32_t mul = (uint32_t)(fc - dr[i]); const len_t os = (ncr - i) % UNROLL; for (l = 0, j = i; l < os; ++l, ++j) { dr[j] += mul * pivs[i][l]; } for (; j < ncr; l += UNROLL, j += UNROLL) { dr[j] += mul * pivs[i][l]; dr[j+1] += mul * pivs[i][l+1]; dr[j+2] += mul * pivs[i][l+2]; dr[j+3] += mul * pivs[i][l+3]; } } if (k == 0) { *pc = -1; return NULL; } cf16_t *row = (cf16_t *)calloc((unsigned long)(ncr-np), sizeof(cf16_t)); for (i = np; i < ncr; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } row[i-np] = (cf16_t)dr[i]; } if (row[0] != 1) { row = normalize_dense_matrix_row_ff_16(row, ncr-np, fc); } *pc = np; return row; } static void probabilistic_sparse_reduced_echelon_form_ff_16( mat_t *mat, const bs_t * const bs, md_t *st ) { len_t i = 0, j, k, l, m; const len_t ncols = mat->nc; const len_t nrl = mat->nrl; const len_t ncr = mat->ncr; const len_t ncl = mat->ncl; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); j = nrl; for (i = 0; i < mat->nru; ++i) { mat->cf_16[j] = bs->cf_16[mat->rr[i][COEFFS]]; mat->rr[i][COEFFS] = j; ++j; } /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; const uint32_t fc = st->fc; const int64_t mod2 = (int64_t)fc * fc; /* compute rows per block */ const len_t nb = (len_t)(floor(sqrt(nrl/3)))+1; const len_t rem = (nrl % nb == 0) ? 0 : 1; const len_t rpb = (nrl / nb) + rem; int64_t *dr = (int64_t *)malloc( (unsigned long)(st->nthrds * ncols) * sizeof(int64_t)); int64_t *mul = (int64_t *)malloc( (unsigned long)(st->nthrds * rpb) * sizeof(int64_t)); /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ #pragma omp parallel for num_threads(st->nthrds) \ private(i, j, k, l, m) \ schedule(dynamic) for (i = 0; i < nb; ++i) { int64_t *drl = dr + (omp_get_thread_num() * ncols); int64_t *mull = mul + (omp_get_thread_num() * rpb); const int32_t nbl = (int32_t) (nrl > (i+1)*rpb ? (i+1)*rpb : nrl); const int32_t nrbl = (int32_t) (nbl - i*rpb); if (nrbl != 0) { hm_t *npiv = NULL; cf16_t *cfs; /* starting column, offset, coefficient array position in tmpcf */ hm_t sc, cfp; len_t bctr = 0; while (bctr < nrbl) { cfp = bctr + i*rpb; sc = 0; /* fill random value array */ for (j = 0; j < nrbl; ++j) { mull[j] = (int64_t)rand() % fc; } /* generate one dense row as random linear combination * of the rows of the block */ memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); for (k = 0, m = i*rpb; m < nbl; ++k, ++m) { npiv = upivs[m]; cfs = bs->cf_16[npiv[COEFFS]]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const hm_t * const ds = npiv + OFFSET; sc = sc < ds[0] ? sc : ds[0]; for (l = 0; l < os; ++l) { drl[ds[l]] -= mull[k] * cfs[l]; drl[ds[l]] += (drl[ds[l]] >> 63) & mod2; } for (; l < len; l += UNROLL) { drl[ds[l]] -= mull[k] * cfs[l]; drl[ds[l]] += (drl[ds[l]] >> 63) & mod2; drl[ds[l+1]] -= mull[k] * cfs[l+1]; drl[ds[l+1]] += (drl[ds[l+1]] >> 63) & mod2; drl[ds[l+2]] -= mull[k] * cfs[l+2]; drl[ds[l+2]] += (drl[ds[l+2]] >> 63) & mod2; drl[ds[l+3]] -= mull[k] * cfs[l+3]; drl[ds[l+3]] += (drl[ds[l+3]] >> 63) & mod2; } } k = 0; cfs = NULL; npiv = NULL; /* do the reduction */ do { free(cfs); cfs = NULL; free(npiv); npiv = NULL; npiv = reduce_dense_row_by_known_pivots_sparse_ff_16( drl, mat, bs, pivs, sc, cfp, 0, 0, 0, st->fc); if (!npiv) { bctr = nrbl; break; } /* normalize coefficient array * NOTE: this has to be done here, otherwise the reduction may * lead to wrong results in a parallel computation since other * threads might directly use the new pivot once it is synced. */ if (mat->cf_16[npiv[COEFFS]][0] != 1) { normalize_sparse_matrix_row_ff_16( mat->cf_16[npiv[COEFFS]], npiv[PRELOOP], npiv[LENGTH], st->fc); } cfs = mat->cf_16[npiv[COEFFS]]; sc = npiv[OFFSET]; k = __sync_bool_compare_and_swap(&pivs[npiv[OFFSET]], NULL, npiv); } while (!k); bctr++; } for (j = i*rpb; j < nbl; ++j) { free(upivs[j]); upivs[j] = NULL; } } } free(mul); mul = NULL; /* construct the trace */ if (st->trace_level == LEARN_TRACER && st->in_final_reduction_step == 0) { construct_trace(st->tr, mat); } /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { free(pivs[i]); pivs[i] = NULL; } len_t npivs = 0; /* number of new pivots */ dr = realloc(dr, (unsigned long)ncols * sizeof(int64_t)); mat->tr = realloc(mat->tr, (unsigned long)ncr * sizeof(hm_t *)); /* interreduce new pivots */ cf16_t *cfs; /* starting column, coefficient array position in tmpcf */ hm_t sc, cfp; for (i = 0; i < ncr; ++i) { k = ncols-1-i; if (pivs[k]) { memset(dr, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = mat->cf_16[pivs[k][COEFFS]]; cfp = pivs[k][COEFFS]; const len_t bi = pivs[k][BINDEX]; const len_t mh = pivs[k][MULT]; const len_t os = pivs[k][PRELOOP]; const len_t len = pivs[k][LENGTH]; const hm_t * const ds = pivs[k] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { dr[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] = (int64_t)cfs[j]; dr[ds[j+1]] = (int64_t)cfs[j+1]; dr[ds[j+2]] = (int64_t)cfs[j+2]; dr[ds[j+3]] = (int64_t)cfs[j+3]; } free(pivs[k]); free(cfs); pivs[k] = NULL; pivs[k] = mat->tr[npivs++] = reduce_dense_row_by_known_pivots_sparse_ff_16( dr, mat, bs, pivs, sc, cfp, mh, bi, 0, st->fc); } } free(pivs); pivs = NULL; free(dr); dr = NULL; mat->tr = realloc(mat->tr, (unsigned long)npivs * sizeof(hi_t *)); st->np = mat->np = mat->nr = mat->sz = npivs; } static void exact_trace_sparse_reduced_echelon_form_ff_16( trace_t *trace, mat_t *mat, const bs_t * const bs, md_t *st ) { len_t i = 0, j, k; hi_t sc = 0; /* starting column */ const len_t ncols = mat->nc; const len_t nrl = mat->nrl; const len_t ncr = mat->ncr; const len_t ncl = mat->ncl; const int32_t nthrds = st->in_final_reduction_step == 1 ? 1 : st->nthrds; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); j = nrl; for (i = 0; i < mat->nru; ++i) { mat->cf_16[j] = bs->cf_16[mat->rr[i][COEFFS]]; mat->rr[i][COEFFS] = j; ++j; } /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; int64_t *dr = (int64_t *)malloc( (unsigned long)(nthrds * ncols) * sizeof(int64_t)); /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ #pragma omp parallel for num_threads(nthrds) \ private(i, j, k, sc) \ schedule(dynamic) for (i = 0; i < nrl; ++i) { int64_t *drl = dr + (omp_get_thread_num() * ncols); hm_t *npiv = upivs[i]; rba_t *rba = mat->rba[i]; cf16_t *cfs = bs->cf_16[npiv[COEFFS]]; const len_t bi = npiv[BINDEX]; const len_t mh = npiv[MULT]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const hm_t * const ds = npiv + OFFSET; k = 0; memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); for (j = 0; j < os; ++j) { drl[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { drl[ds[j]] = (int64_t)cfs[j]; drl[ds[j+1]] = (int64_t)cfs[j+1]; drl[ds[j+2]] = (int64_t)cfs[j+2]; drl[ds[j+3]] = (int64_t)cfs[j+3]; } cfs = NULL; do { sc = npiv[OFFSET]; free(npiv); npiv = NULL; free(cfs); npiv = mat->tr[i] = trace_reduce_dense_row_by_known_pivots_sparse_ff_16( rba, drl, mat, bs, pivs, sc, i, mh, bi, st->fc); if (!npiv) { break; } /* normalize coefficient array * NOTE: this has to be done here, otherwise the reduction may * lead to wrong results in a parallel computation since other * threads might directly use the new pivot once it is synced. */ if (mat->cf_16[npiv[COEFFS]][0] != 1) { normalize_sparse_matrix_row_ff_16( mat->cf_16[npiv[COEFFS]], npiv[PRELOOP], npiv[LENGTH], st->fc); } k = __sync_bool_compare_and_swap(&pivs[npiv[OFFSET]], NULL, npiv); cfs = mat->cf_16[npiv[COEFFS]]; } while (!k); } /* construct the trace */ construct_trace(trace, mat); /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { free(pivs[i]); pivs[i] = NULL; } len_t npivs = 0; /* number of new pivots */ dr = realloc(dr, (unsigned long)ncols * sizeof(int64_t)); mat->tr = realloc(mat->tr, (unsigned long)ncr * sizeof(hm_t *)); /* interreduce new pivots */ cf16_t *cfs; hm_t cf_array_pos; for (i = 0; i < ncr; ++i) { k = ncols-1-i; if (pivs[k]) { memset(dr, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = mat->cf_16[pivs[k][COEFFS]]; cf_array_pos = pivs[k][COEFFS]; const len_t bi = pivs[k][BINDEX]; const len_t mh = pivs[k][MULT]; const len_t os = pivs[k][PRELOOP]; const len_t len = pivs[k][LENGTH]; const hm_t * const ds = pivs[k] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { dr[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] = (int64_t)cfs[j]; dr[ds[j+1]] = (int64_t)cfs[j+1]; dr[ds[j+2]] = (int64_t)cfs[j+2]; dr[ds[j+3]] = (int64_t)cfs[j+3]; } free(pivs[k]); free(cfs); pivs[k] = NULL; pivs[k] = mat->tr[npivs++] = reduce_dense_row_by_known_pivots_sparse_ff_16( dr, mat, bs, pivs, sc, cf_array_pos, mh, bi, 0, st->fc); } } free(pivs); pivs = NULL; free(dr); dr = NULL; mat->tr = realloc(mat->tr, (unsigned long)npivs * sizeof(hi_t *)); st->np = mat->np = mat->nr = mat->sz = npivs; } static void exact_sparse_reduced_echelon_form_ff_16( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { len_t i = 0, j, k; hi_t sc = 0; /* starting column */ const len_t ncols = mat->nc; const len_t nrl = mat->nrl; const len_t ncr = mat->ncr; const len_t ncl = mat->ncl; const int32_t nthrds = st->in_final_reduction_step == 1 ? 1 : st->nthrds; len_t bad_prime = 0; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); if (st->in_final_reduction_step == 0) { memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); } else { for (i = 0; i < mat->nru; ++i) { pivs[mat->rr[i][OFFSET]] = mat->rr[i]; } } j = nrl; for (i = 0; i < mat->nru; ++i) { mat->cf_16[j] = bs->cf_16[mat->rr[i][COEFFS]]; mat->rr[i][COEFFS] = j; ++j; } /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; int64_t *dr = (int64_t *)malloc( (unsigned long)(nthrds * ncols) * sizeof(int64_t)); /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ #pragma omp parallel for num_threads(nthrds) \ private(i, j, k, sc) \ schedule(dynamic) for (i = 0; i < nrl; ++i) { if (bad_prime == 0) { int64_t *drl = dr + (omp_get_thread_num() * ncols); hm_t *npiv = upivs[i]; cf16_t *cfs = tbr->cf_16[npiv[COEFFS]]; const len_t bi = npiv[BINDEX]; const len_t mh = npiv[MULT]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const hm_t * const ds = npiv + OFFSET; k = 0; memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); for (j = 0; j < os; ++j) { drl[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { drl[ds[j]] = (int64_t)cfs[j]; drl[ds[j+1]] = (int64_t)cfs[j+1]; drl[ds[j+2]] = (int64_t)cfs[j+2]; drl[ds[j+3]] = (int64_t)cfs[j+3]; } cfs = NULL; do { /* If we do normal form computations the first monomial in the polynomial might not be a known pivot, thus setting it to npiv[OFFSET] can lead to wrong results. */ sc = st->nf == 0 ? npiv[OFFSET] : 0; free(npiv); npiv = NULL; free(cfs); cfs = NULL; npiv = mat->tr[i] = reduce_dense_row_by_known_pivots_sparse_ff_16( drl, mat, bs, pivs, sc, i, mh, bi, st->trace_level == LEARN_TRACER, st->fc); if (st->nf > 0) { if (!npiv) { mat->tr[i] = NULL; break; } mat->tr[i] = npiv; cfs = mat->cf_16[npiv[COEFFS]]; break; } else { if (!npiv) { break; } /* normalize coefficient array * NOTE: this has to be done here, otherwise the reduction may * lead to wrong results in a parallel computation since other * threads might directly use the new pivot once it is synced. */ if (mat->cf_16[npiv[COEFFS]][0] != 1) { normalize_sparse_matrix_row_ff_16( mat->cf_16[npiv[COEFFS]], npiv[PRELOOP], npiv[LENGTH], st->fc); } k = __sync_bool_compare_and_swap(&pivs[npiv[OFFSET]], NULL, npiv); cfs = mat->cf_16[npiv[COEFFS]]; } } while (!k); } } if (bad_prime == 1) { for (i = 0; i < ncl+ncr; ++i) { free(pivs[i]); pivs[i] = NULL; } mat->np = 0; if (st->info_level > 0) { fprintf(stderr, "Zero reduction while applying tracer, bad prime.\n"); } return; } /* construct the trace */ if (st->trace_level == LEARN_TRACER && st->in_final_reduction_step == 0) { construct_trace(st->tr, mat); } /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { free(pivs[i]); pivs[i] = NULL; } len_t npivs = 0; /* number of new pivots */ if (st->nf == 0 && st->in_final_reduction_step == 0) { dr = realloc(dr, (unsigned long)ncols * sizeof(int64_t)); mat->tr = realloc(mat->tr, (unsigned long)ncr * sizeof(hm_t *)); /* interreduce new pivots */ cf16_t *cfs; hm_t cf_array_pos; for (i = 0; i < ncr; ++i) { k = ncols-1-i; if (pivs[k]) { memset(dr, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = mat->cf_16[pivs[k][COEFFS]]; cf_array_pos = pivs[k][COEFFS]; const len_t bi = pivs[k][BINDEX]; const len_t mh = pivs[k][MULT]; const len_t os = pivs[k][PRELOOP]; const len_t len = pivs[k][LENGTH]; const hm_t * const ds = pivs[k] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { dr[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] = (int64_t)cfs[j]; dr[ds[j+1]] = (int64_t)cfs[j+1]; dr[ds[j+2]] = (int64_t)cfs[j+2]; dr[ds[j+3]] = (int64_t)cfs[j+3]; } free(pivs[k]); free(cfs); pivs[k] = NULL; pivs[k] = mat->tr[npivs++] = reduce_dense_row_by_known_pivots_sparse_ff_16( dr, mat, bs, pivs, sc, cf_array_pos, mh, bi, 0, st->fc); } } mat->tr = realloc(mat->tr, (unsigned long)npivs * sizeof(hi_t *)); st->np = mat->np = mat->nr = mat->sz = npivs; } else { st->np = mat->np = mat->nr = mat->sz = nrl; } free(pivs); pivs = NULL; free(dr); dr = NULL; } static int exact_application_sparse_reduced_echelon_form_ff_16( mat_t *mat, const bs_t * const bs, md_t *st ) { len_t i = 0, j, k; hi_t sc = 0; /* starting column */ const len_t ncols = mat->nc; const len_t nrl = mat->nrl; const len_t ncr = mat->ncr; const len_t ncl = mat->ncl; const int32_t nthrds = st->in_final_reduction_step == 1 ? 1 : st->nthrds; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); j = nrl; for (i = 0; i < mat->nru; ++i) { mat->cf_16[j] = bs->cf_16[mat->rr[i][COEFFS]]; mat->rr[i][COEFFS] = j; ++j; } /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; int64_t *dr = (int64_t *)malloc( (unsigned long)(nthrds * ncols) * sizeof(int64_t)); /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ int flag = 1; #pragma omp parallel for num_threads(nthrds) \ private(i, j, k, sc) \ schedule(dynamic) for (i = 0; i < nrl; ++i) { if (flag == 1) { int64_t *drl = dr + (omp_get_thread_num() * ncols); hm_t *npiv = upivs[i]; cf16_t *cfs = bs->cf_16[npiv[COEFFS]]; const len_t bi = npiv[BINDEX]; const len_t mh = npiv[MULT]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const hm_t * const ds = npiv + OFFSET; k = 0; memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); for (j = 0; j < os; ++j) { drl[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { drl[ds[j]] = (int64_t)cfs[j]; drl[ds[j+1]] = (int64_t)cfs[j+1]; drl[ds[j+2]] = (int64_t)cfs[j+2]; drl[ds[j+3]] = (int64_t)cfs[j+3]; } cfs = NULL; do { sc = npiv[OFFSET]; free(npiv); free(cfs); npiv = mat->tr[i] = reduce_dense_row_by_known_pivots_sparse_ff_16( drl, mat, bs, pivs, sc, i, mh, bi, 0, st->fc); if (!npiv) { fprintf(stderr, "Unlucky prime detected, row reduced to zero."); flag = 0; } /* normalize coefficient array * NOTE: this has to be done here, otherwise the reduction may * lead to wrong results in a parallel computation since other * threads might directly use the new pivot once it is synced. */ if (mat->cf_16[npiv[COEFFS]][0] != 1) { normalize_sparse_matrix_row_ff_16( mat->cf_16[npiv[COEFFS]], npiv[PRELOOP], npiv[LENGTH], st->fc); } k = __sync_bool_compare_and_swap(&pivs[npiv[OFFSET]], NULL, npiv); cfs = mat->cf_16[npiv[COEFFS]]; } while (!k); } } /* unlucky prime found */ if (flag == 0) { return 1; } /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { free(pivs[i]); pivs[i] = NULL; } len_t npivs = 0; /* number of new pivots */ dr = realloc(dr, (unsigned long)ncols * sizeof(int64_t)); mat->tr = realloc(mat->tr, (unsigned long)ncr * sizeof(hm_t *)); /* interreduce new pivots */ cf16_t *cfs; hm_t cf_array_pos; for (i = 0; i < ncr; ++i) { k = ncols-1-i; if (pivs[k]) { memset(dr, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = mat->cf_16[pivs[k][COEFFS]]; cf_array_pos = pivs[k][COEFFS]; const len_t bi = pivs[k][BINDEX]; const len_t mh = pivs[k][MULT]; const len_t os = pivs[k][PRELOOP]; const len_t len = pivs[k][LENGTH]; const hm_t * const ds = pivs[k] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { dr[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] = (int64_t)cfs[j]; dr[ds[j+1]] = (int64_t)cfs[j+1]; dr[ds[j+2]] = (int64_t)cfs[j+2]; dr[ds[j+3]] = (int64_t)cfs[j+3]; } free(pivs[k]); free(cfs); pivs[k] = NULL; pivs[k] = mat->tr[npivs++] = reduce_dense_row_by_known_pivots_sparse_ff_16( dr, mat, bs, pivs, sc, cf_array_pos, mh, bi, 0, st->fc); } } free(pivs); pivs = NULL; free(dr); dr = NULL; mat->tr = realloc(mat->tr, (unsigned long)npivs * sizeof(hi_t *)); st->np = mat->np = mat->nr = mat->sz = npivs; return 0; } static cf16_t **sparse_AB_CD_linear_algebra_ff_16( mat_t *mat, const bs_t * bs, md_t *st ) { len_t i = 0, j; hi_t sc = 0; /* starting column */ const len_t ncols = mat->nc; const len_t nrl = mat->nrl; const len_t ncl = mat->ncl; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; /* dense rows representing updated D part; * after reducing CD part with AB */ cf16_t **drs = (cf16_t **)calloc((unsigned long)nrl, sizeof(cf16_t *)); int64_t *dr = (int64_t *)malloc( (unsigned long)(st->nthrds * ncols) * sizeof(int64_t)); /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ #pragma omp parallel for num_threads(st->nthrds) \ private(i, j, sc) \ schedule(dynamic) for (i = 0; i < nrl; ++i) { cf16_t *cfs = NULL; int64_t *drl = dr + (omp_get_thread_num() * ncols); hm_t *npiv = upivs[i]; /* do the reduction */ memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = bs->cf_16[npiv[COEFFS]]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const hm_t * const ds = npiv + OFFSET; for (j = 0; j < os; ++j) { drl[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { drl[ds[j]] = (int64_t)cfs[j]; drl[ds[j+1]] = (int64_t)cfs[j+1]; drl[ds[j+2]] = (int64_t)cfs[j+2]; drl[ds[j+3]] = (int64_t)cfs[j+3]; } sc = 0; /* row columns are not sorted, so we have to start at 0 */ free(npiv); drs[i] = reduce_dense_row_by_old_pivots_ff_16( drl, mat, bs, pivs, sc, st->fc); } free(dr); dr = NULL; /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { free(pivs[i]); pivs[i] = NULL; } free(pivs); pivs = NULL; /* remove NULL dense rows */ len_t npivs = 0; /* number of new pivots */ for (i = 0; i < nrl; ++i) { if (drs[i] != NULL) { drs[npivs++] = drs[i]; } } if (npivs == 0) { free(drs); drs = NULL; } st->np = mat->np = npivs; return drs; } static cf16_t **interreduce_dense_matrix_ff_16( cf16_t **dm, const len_t ncr, const uint32_t fc ) { len_t i, j, k, l; int64_t *dr = malloc((unsigned long)ncr * sizeof(int64_t)); for (i = 0; i < ncr; ++i) { k = ncr-1-i; if (dm[k]) { /* printf("interreduce dm[%d]\n", i); */ memset(dr, 0, (unsigned long)ncr * sizeof(int64_t)); const len_t npc = ncr - k; const len_t os = npc % UNROLL; for (j = k, l = 0; l < os; ++j, ++l) { dr[j] = (int64_t)dm[k][l]; } for (; l < npc; j += UNROLL, l += UNROLL) { dr[j] = (int64_t)dm[k][l]; dr[j+1] = (int64_t)dm[k][l+1]; dr[j+2] = (int64_t)dm[k][l+2]; dr[j+3] = (int64_t)dm[k][l+3]; } free(dm[k]); dm[k] = NULL; /* start with previous pivot the reduction process, so keep the * pivot element as it is */ dm[k] = reduce_dense_row_by_dense_new_pivots_ff_16( dr, &k, dm, ncr, fc); } } free(dr); return dm; } static cf16_t **exact_dense_linear_algebra_ff_16( cf16_t **dm, mat_t *mat, md_t *st ) { len_t i, j, k, l, npivs; const len_t nrows = mat->np; /* we need the pivots until now here */ const len_t ncr = mat->ncr; /* rows already representing new pivots */ cf16_t **nps = (cf16_t **)calloc((unsigned long)ncr, sizeof(cf16_t *)); /* rows to be further reduced */ cf16_t **tbr = (cf16_t **)calloc((unsigned long)nrows, sizeof(cf16_t *)); int64_t *dr = (int64_t *)malloc( (unsigned long)(st->nthrds * ncr) * sizeof(int64_t)); /* separate rows already representing new pivots and rows to * be further reduced by these new pivots */ j = 0; npivs = 0; for (i = 0; i < nrows; ++i) { if (dm[i] != NULL) { k = 0; while (dm[i][k] == 0) { ++k; } if (nps[k] == NULL) { /* we have a pivot, cut the dense row down to start * at the first nonzero entry */ /* printf("ncr - k = %d - %d\n", ncr, k); */ memmove(dm[i], dm[i]+k, (unsigned long)(ncr-k) * sizeof(cf16_t)); dm[i] = realloc(dm[i], (unsigned long)(ncr-k) * sizeof(cf16_t)); nps[k] = dm[i]; if (nps[k][0] != 1) { nps[k] = normalize_dense_matrix_row_ff_16(nps[k], ncr-k, st->fc); } } else { tbr[j++] = dm[i]; } } } free(dm); dm = NULL; const len_t ntr = j; tbr = realloc(tbr, (unsigned long)ntr * sizeof(cf16_t *)); /* offset modulo 4 for loop unrolling, +1 due to storing the first * nonzero entry at the first position */ /* reduction process to get all possible pivots, no interreduction here */ #pragma omp parallel for num_threads(st->nthrds) \ private(i, j, k, l) shared(nps, tbr) \ schedule(dynamic) for (i = 0; i < ntr; ++i) { int64_t *drl = dr + (omp_get_thread_num() * ncr); memset(drl, 0, (unsigned long)ncr * sizeof(int64_t)); hm_t npc = 0; hm_t os = 0; cf16_t *npiv = tbr[i]; os = (ncr-npc) % UNROLL; for (l = 0, j = npc; l < os; ++l, ++j) { drl[j] = (int64_t)npiv[l]; } for (; j < ncr; l += UNROLL, j += UNROLL) { drl[j] = (int64_t)npiv[l]; drl[j+1] = (int64_t)npiv[l+1]; drl[j+2] = (int64_t)npiv[l+2]; drl[j+3] = (int64_t)npiv[l+3]; } do { free(npiv); npiv = NULL; npiv = reduce_dense_row_by_dense_new_pivots_ff_16( drl, &npc, nps, mat->ncr, st->fc); if (npc == -1) { break; } k = __sync_bool_compare_and_swap(&nps[npc], NULL, npiv); /* some other thread has already added a pivot so we have to * recall the dense reduction process */ } while (!k); } /* count number of pivots */ const len_t os = ncr % UNROLL; for (i = 0; i < os; ++i) { if (nps[i] != NULL) { npivs++; } } for (; i < ncr; i += UNROLL) { if (nps[i] != NULL) { npivs++; } if (nps[i+1] != NULL) { npivs++; } if (nps[i+2] != NULL) { npivs++; } if (nps[i+3] != NULL) { npivs++; } } st->np = mat->np = npivs; free(tbr); free(dr); return nps; } static cf16_t **probabilistic_dense_linear_algebra_ff_16( cf16_t **dm, mat_t *mat, md_t *st ) { len_t i, j, k, l, m, npivs; const uint32_t fc = st->fc; const len_t nrows = mat->np; /* we need the pivots until now here */ const len_t ncols = mat->nc; const len_t ncr = mat->ncr; /* rows already representing new pivots */ cf16_t **nps = (cf16_t **)calloc((unsigned long)ncr, sizeof(cf16_t *)); /* rows to be further reduced */ cf16_t **tbr = (cf16_t **)calloc((unsigned long)nrows, sizeof(cf16_t *)); /* separate rows already representing new pivots and rows to * be further reduced by these new pivots */ j = 0; npivs = 0; for (i = 0; i < nrows; ++i) { if (dm[i] != NULL) { k = 0; while (dm[i][k] == 0) { ++k; } if (nps[k] == NULL) { /* we have a pivot, cut the dense row down to start * at the first nonzero entry */ memmove(dm[i], dm[i]+k, (unsigned long)(ncr-k) * sizeof(cf16_t)); dm[i] = realloc(dm[i], (unsigned long)(ncr-k) * sizeof(cf16_t)); nps[k] = dm[i]; if (nps[k][0] != 1) { nps[k] = normalize_dense_matrix_row_ff_16(nps[k], ncr-k, st->fc); } } else { tbr[j++] = dm[i]; } } } free(dm); dm = NULL; const len_t ntr = j; tbr = realloc(tbr, (unsigned long)ntr * sizeof(cf16_t *)); const int64_t mod2 = (int64_t)st->fc * st->fc; /* compute rows per block */ const len_t nb = (len_t)(floor(sqrt(ntr/3)))+1; const len_t rem = (ntr % nb == 0) ? 0 : 1; const len_t rpb = (ntr / nb) + rem; int64_t *dr = (int64_t *)malloc( (unsigned long)(st->nthrds * ncols) * sizeof(int64_t)); int64_t *mul = (int64_t *)malloc( (unsigned long)(st->nthrds * rpb) * sizeof(int64_t)); /* reduction process to get all possible pivots, no interreduction here */ #pragma omp parallel for num_threads(st->nthrds) \ private(i, j, k, l) shared(nps, tbr) \ schedule(dynamic) for (i = 0; i < ntr; ++i) { int64_t *drl = dr + (omp_get_thread_num() * ncr); int64_t *mull = mul + (omp_get_thread_num() * rpb); const int32_t nbl = (int32_t) (ntr > (i+1)*rpb ? (i+1)*rpb : ntr); const int32_t nrbl = (int32_t) (nbl - i*rpb); if (nrbl > 0) { hm_t npc; hm_t os; cf16_t *tmp; len_t bctr = 0; while (bctr < nrbl) { npc = 0; os = ncr % UNROLL; /* fill random value array */ for (j = 0; j < nrbl; ++j) { mull[j] = (int64_t)rand() % fc; } /* generate one dense row as random linear combination * of the rows of the block */ memset(drl, 0, (unsigned long)ncr * sizeof(int64_t)); for (k = 0, m = i*rpb; m < nbl; ++k, ++m) { tmp = tbr[m]; for (l = 0, j = npc; l < os; ++l, ++j) { drl[j] -= mull[k] * tmp[l]; drl[j] += (drl[j] >> 63) & mod2; } for (; j < ncr; l += UNROLL, j += UNROLL) { drl[j] -= mull[k] * tmp[l]; drl[j] += (drl[j] >> 63) & mod2; drl[j+1] -= mull[k] * tmp[l+1]; drl[j+1] += (drl[j+1] >> 63) & mod2; drl[j+2] -= mull[k] * tmp[l+2]; drl[j+2] += (drl[j+2] >> 63) & mod2; drl[j+3] -= mull[k] * tmp[l+3]; drl[j+3] += (drl[j+3] >> 63) & mod2; } } k = 0; npc = 0; /* do the reduction */ tmp = NULL; do { free(tmp); tmp = reduce_dense_row_by_dense_new_pivots_ff_16( drl, &npc, nps, mat->ncr, st->fc); if (npc == -1) { bctr = nrbl; break; } k = __sync_bool_compare_and_swap(&nps[npc], NULL, tmp); /* some other thread has already added a pivot so we have to * recall the dense reduction process */ } while (!k); bctr++; } for (j = i*rpb; j < nbl; ++j) { free(tbr[j]); tbr[j] = NULL; } } } /* count number of pivots */ const len_t os = ncr % UNROLL; for (i = 0; i < os; ++i) { if (nps[i] != NULL) { npivs++; } } for (; i < ncr; i += UNROLL) { if (nps[i] != NULL) { npivs++; } if (nps[i+1] != NULL) { npivs++; } if (nps[i+2] != NULL) { npivs++; } if (nps[i+3] != NULL) { npivs++; } } st->np = mat->np = npivs; free(mul); free(tbr); free(dr); return nps; } static cf16_t **probabilistic_sparse_dense_echelon_form_ff_16( mat_t *mat, const bs_t * const bs, md_t *st ) { len_t i = 0, j, k, l, m, npivs; const len_t nru = mat->nru; const len_t nrl = mat->nrl; const len_t ncr = mat->ncr; const len_t ncols = mat->nc; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; /* rows already representing new pivots */ cf16_t **nps = (cf16_t **)calloc((unsigned long)ncr, sizeof(cf16_t *)); const uint32_t fc = st->fc; const int64_t mod2 = (int64_t)fc * fc; /* compute rows per block */ const len_t nb = (len_t)(floor(sqrt(nrl/3)))+1; const len_t rem = (nrl % nb == 0) ? 0 : 1; const len_t rpb = (nrl / nb) + rem; int64_t *dr = (int64_t *)malloc( (unsigned long)(st->nthrds * ncols) * sizeof(int64_t)); int64_t *mul = (int64_t *)malloc( (unsigned long)(st->nthrds * rpb) * sizeof(int64_t)); /* reduction process to get all possible pivots, no interreduction here */ #pragma omp parallel for num_threads(st->nthrds) \ private(i, j, k, l, m) shared(nps) \ schedule(dynamic) for (i = 0; i < nb; ++i) { int64_t *drl = dr + (omp_get_thread_num() * ncols); int64_t *mull = mul + (omp_get_thread_num() * rpb); const int32_t nbl = (int32_t) (nrl > (i+1)*rpb ? (i+1)*rpb : nrl); const int32_t nrbl = (int32_t) (nbl - i*rpb); if (nrbl > 0) { hm_t *npiv; cf16_t *tmp; hm_t npc; len_t bctr = 0; while (bctr < nrbl) { npc = 0; /* fill random value array */ for (j = 0; j < nrbl; ++j) { mull[j] = (int64_t)rand() % fc; } /* generate one dense row as random linear combination * of the rows of the block */ memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); for (k = 0, m = i*rpb; m < nbl; ++k, ++m) { npiv = upivs[m]; tmp = bs->cf_16[npiv[COEFFS]]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const hm_t * const ds = npiv + OFFSET; for (l = 0; l < os; ++l) { drl[ds[l]] -= mull[k] * tmp[l]; drl[ds[l]] += (drl[ds[l]] >> 63) & mod2; } for (; l < len; l += UNROLL) { drl[ds[l]] -= mull[k] * tmp[l]; drl[ds[l]] += (drl[ds[l]] >> 63) & mod2; drl[ds[l+1]] -= mull[k] * tmp[l+1]; drl[ds[l+1]] += (drl[ds[l+1]] >> 63) & mod2; drl[ds[l+2]] -= mull[k] * tmp[l+2]; drl[ds[l+2]] += (drl[ds[l+2]] >> 63) & mod2; drl[ds[l+3]] -= mull[k] * tmp[l+3]; drl[ds[l+3]] += (drl[ds[l+3]] >> 63) & mod2; } } k = 0; npc = 0; /* do the reduction */ tmp = NULL; do { free(tmp); tmp = reduce_dense_row_by_all_pivots_ff_16( drl, mat, bs, &npc, pivs, nps, st->fc); if (npc == -1) { bctr = nrbl; break; } k = __sync_bool_compare_and_swap(&nps[npc], NULL, tmp); /* some other thread has already added a pivot so we have to * recall the dense reduction process */ } while (!k); bctr++; } for (j = i*rpb; j < nbl; ++j) { free(upivs[j]); upivs[j] = NULL; } } } npivs = 0; /* count number of pivots */ const len_t os = ncr % UNROLL; for (i = 0; i < os; ++i) { if (nps[i] != NULL) { npivs++; } } for (; i < ncr; i += UNROLL) { if (nps[i] != NULL) { npivs++; } if (nps[i+1] != NULL) { npivs++; } if (nps[i+2] != NULL) { npivs++; } if (nps[i+3] != NULL) { npivs++; } } st->np = mat->np = npivs; for (i = 0; i < nru; ++i) { free(pivs[i]); } free(pivs); pivs = NULL; free(mul); mul = NULL; free(dr); dr = NULL; return nps; } static void convert_to_sparse_matrix_rows_ff_16( mat_t *mat, cf16_t * const * const dm ) { if (mat->np == 0) { return; } len_t i, j, k, l, m; cf16_t *cfs; hm_t *dts, *dss; const len_t ncr = mat->ncr; const len_t ncl = mat->ncl; mat->tr = realloc(mat->tr, (unsigned long)mat->np * sizeof(hm_t *)); mat->cf_16 = realloc(mat->cf_16, (unsigned long)mat->np * sizeof(cf16_t *)); l = 0; for (i = 0; i < ncr; ++i) { m = ncr-1-i; if (dm[m] != NULL) { cfs = malloc((unsigned long)(ncr-m) * sizeof(cf16_t)); dts = malloc((unsigned long)(ncr-m+OFFSET) * sizeof(hm_t)); const hm_t len = ncr-m; const hm_t os = len % UNROLL; const hm_t shift = ncl+m; dss = dts + OFFSET; for (k = 0, j = 0; j < os; ++j) { if (dm[m][j] != 0) { cfs[k] = dm[m][j]; dss[k++] = j+shift; } } for (; j < len; j += UNROLL) { if (dm[m][j] != 0) { cfs[k] = dm[m][j]; dss[k++] = j+shift; } if (dm[m][j+1] != 0) { cfs[k] = dm[m][j+1]; dss[k++] = j+1+shift; } if (dm[m][j+2] != 0) { cfs[k] = dm[m][j+2]; dss[k++] = j+2+shift; } if (dm[m][j+3] != 0) { cfs[k] = dm[m][j+3]; dss[k++] = j+3+shift; } } /* store meta data in first entries */ dts[COEFFS] = l; /* position of coefficient array in tmpcf */ dts[PRELOOP] = k % UNROLL; dts[LENGTH] = k; /* adjust memory usage */ dts = realloc(dts, (unsigned long)(k+OFFSET) * sizeof(hm_t)); cfs = realloc(cfs, (unsigned long)k * sizeof(cf16_t)); /* link to basis */ mat->tr[l] = dts; mat->cf_16[l] = cfs; l++; } } } /* NOTE: this note is about the different linear algebra implementations: * exact and probabilistic linear algebra differ only in the last, * dense reduction step: the reduction of CD via AB is sparse and * the same for both. this generates a dense D' part which is then * either reduced via exact linear algebra or via probabilistic * linear algebra */ static void probabilistic_sparse_linear_algebra_ff_16( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* allocate temporary storage space for sparse * coefficients of all pivot rows */ mat->cf_16 = realloc(mat->cf_16, (unsigned long)mat->nr * sizeof(cf16_t *)); probabilistic_sparse_reduced_echelon_form_ff_16(mat, bs, st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } /* In f4: tbr == bs in nf: tbr are the polynomials to be reduced w.r.t. bs */ static void exact_sparse_linear_algebra_ff_16( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* allocate temporary storage space for sparse * coefficients of all pivot rows */ mat->cf_16 = realloc(mat->cf_16, (unsigned long)mat->nr * sizeof(cf16_t *)); exact_sparse_reduced_echelon_form_ff_16(mat, tbr, bs, st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static int exact_application_sparse_linear_algebra_ff_16( mat_t *mat, const bs_t * const bs, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); int ret; /* allocate temporary storage space for sparse * coefficients of all pivot rows */ mat->cf_16 = realloc(mat->cf_16, (unsigned long)mat->nr * sizeof(cf16_t *)); ret = exact_application_sparse_reduced_echelon_form_ff_16(mat, bs, st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } return ret; } static void exact_trace_sparse_linear_algebra_ff_16( trace_t *trace, mat_t *mat, const bs_t * const bs, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* allocate temporary storage space for sparse * coefficients of all pivot rows */ mat->cf_16 = realloc(mat->cf_16, (unsigned long)mat->nr * sizeof(cf16_t *)); exact_trace_sparse_reduced_echelon_form_ff_16(trace, mat, bs, st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static void exact_sparse_dense_linear_algebra_ff_16( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { len_t i; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); const len_t ncr = mat->ncr; /* generate updated dense D part via reduction of CD with AB */ cf16_t **dm; dm = sparse_AB_CD_linear_algebra_ff_16(mat, bs, st); if (mat->np > 0) { dm = exact_dense_linear_algebra_ff_16(dm, mat, st); dm = interreduce_dense_matrix_ff_16(dm, ncr, st->fc); } /* convert dense matrix back to sparse matrix representation, * use tmpcf for storing the coefficient arrays */ convert_to_sparse_matrix_rows_ff_16(mat, dm); /* free dm */ if (dm) { for (i = 0; i < ncr; ++i) { free(dm[i]); } free(dm); dm = NULL; } /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static void probabilistic_sparse_dense_linear_algebra_ff_16_2( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { len_t i; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); const len_t ncr = mat->ncr; /* generate updated dense D part via reduction of CD with AB */ cf16_t **dm; dm = sparse_AB_CD_linear_algebra_ff_16(mat, bs, st); if (mat->np > 0) { dm = probabilistic_dense_linear_algebra_ff_16(dm, mat, st); dm = interreduce_dense_matrix_ff_16(dm, mat->ncr, st->fc); } /* convert dense matrix back to sparse matrix representation, * use tmpcf for storing the coefficient arrays */ convert_to_sparse_matrix_rows_ff_16(mat, dm); /* free dm */ if (dm) { for (i = 0; i < ncr; ++i) { free(dm[i]); } free(dm); dm = NULL; } /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static void probabilistic_sparse_dense_linear_algebra_ff_16( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { len_t i; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); const len_t ncr = mat->ncr; /* generate updated dense D part via reduction of CD with AB */ cf16_t **dm = NULL; mat->np = 0; dm = probabilistic_sparse_dense_echelon_form_ff_16(mat, bs, st); dm = interreduce_dense_matrix_ff_16(dm, mat->ncr, st->fc); /* convert dense matrix back to sparse matrix representation, * use tmpcf for storing the coefficient arrays */ convert_to_sparse_matrix_rows_ff_16(mat, dm); /* free dm */ if (dm) { for (i = 0; i < ncr; ++i) { free(dm[i]); } free(dm); dm = NULL; } /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static void interreduce_matrix_rows_ff_16( mat_t *mat, bs_t *bs, md_t *st, const int free_basis ) { len_t i, j, k, l; const len_t nrows = mat->nr; const len_t ncols = mat->nc; /* adjust displaying timings for statistic printout */ if (st->info_level > 1) { printf(" "); } /* for interreduction steps like the final basis reduction we need to allocate memory for rba here, even so we do not use it at all */ mat->rba = (rba_t **)malloc((unsigned long)ncols * sizeof(rba_t *)); const unsigned long len = ncols / 32 + ((ncols % 32) != 0); for (i = 0; i < ncols; ++i) { mat->rba[i] = (rba_t *)calloc(len, sizeof(rba_t)); } mat->tr = realloc(mat->tr, (unsigned long)ncols * sizeof(hm_t *)); mat->cf_16 = realloc(mat->cf_16, (unsigned long)ncols * sizeof(cf16_t *)); memset(mat->cf_16, 0, (unsigned long)ncols * sizeof(cf16_t *)); hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); /* copy coefficient arrays from basis in matrix, maybe * several rows need the same coefficient arrays, but we * cannot share them here. */ for (i = 0; i < nrows; ++i) { pivs[mat->rr[i][OFFSET]] = mat->rr[i]; } int64_t *dr = (int64_t *)malloc((unsigned long)ncols * sizeof(int64_t)); /* interreduce new pivots */ cf16_t *cfs; /* starting column, coefficient array position in tmpcf */ hm_t sc; k = nrows - 1; for (i = 0; i < ncols; ++i) { l = ncols-1-i; if (pivs[l] != NULL) { memset(dr, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = bs->cf_16[pivs[l][COEFFS]]; const len_t bi = pivs[l][BINDEX]; const len_t mh = pivs[l][MULT]; const len_t os = pivs[l][PRELOOP]; const len_t len = pivs[l][LENGTH]; const hm_t * const ds = pivs[l] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { dr[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] = (int64_t)cfs[j]; dr[ds[j+1]] = (int64_t)cfs[j+1]; dr[ds[j+2]] = (int64_t)cfs[j+2]; dr[ds[j+3]] = (int64_t)cfs[j+3]; } free(pivs[l]); pivs[l] = NULL; pivs[l] = mat->tr[k--] = reduce_dense_row_by_known_pivots_sparse_ff_16( dr, mat, bs, pivs, sc, l, mh, bi, 0, st->fc); } } for (i = 0; i < ncols; ++i) { free(mat->rba[i]); mat->rba[i] = NULL; } if (free_basis != 0) { /* free now all polynomials in the basis and reset bs->ld to 0. */ free_basis_elements(bs); } free(mat->rr); mat->rr = NULL; st->np = mat->np = nrows; free(pivs); free(dr); } msolve-0.6.5/src/neogb/la_ff_32.c000066400000000000000000004223571456710632100164510ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "data.h" /* That's also enough if AVX512 is avaialable on the system */ #if defined HAVE_AVX2 #include #elif defined __aarch64__ #include #endif static inline cf32_t *normalize_dense_matrix_row_ff_32( cf32_t *row, const hm_t len, const uint32_t fc ) { len_t i; const hm_t os = len % UNROLL; const uint32_t inv = mod_p_inverse_32(row[0], fc); for (i = 1; i < os; ++i) { row[i] = (cf32_t)(((uint64_t)row[i] * inv) % fc); } /* we need to set i to os since os < 1 is possible */ for (i = os; i < len; i += UNROLL) { row[i] = (cf32_t)(((uint64_t)row[i] * inv) % fc); row[i+1] = (cf32_t)(((uint64_t)row[i+1] * inv) % fc); row[i+2] = (cf32_t)(((uint64_t)row[i+2] * inv) % fc); row[i+3] = (cf32_t)(((uint64_t)row[i+3] * inv) % fc); } row[0] = 1; return row; } static inline void normalize_dense_matrix_row_kernel_ff_32( cf32_t *row, const len_t start, const len_t nc, const uint32_t fc ) { len_t i; const len_t len = nc; const len_t os = len % UNROLL; const int64_t inv = (int64_t)mod_p_inverse_32(row[start], fc); for (i = start; i < os; ++i) { row[i] = (cf32_t)(((uint64_t)row[i] * inv) % fc); } /* we need to set i to os since os < 1 is possible */ for (i = os; i < len; i += UNROLL) { row[i] = (cf32_t)(((uint64_t)row[i] * inv) % fc); row[i+1] = (cf32_t)(((uint64_t)row[i+1] * inv) % fc); row[i+2] = (cf32_t)(((uint64_t)row[i+2] * inv) % fc); row[i+3] = (cf32_t)(((uint64_t)row[i+3] * inv) % fc); } } /* unused at the moment */ #if 0 static int reduce_dense_row_by_dense_pivots_ff_32( int64_t *dr, cf32_t *dm, cf32_t **pivs, const len_t start, const len_t nc, const len_t fc ) { len_t i, j; const int64_t mod = (int64_t)fc; const int64_t mod2 = (int64_t)fc * fc; for (i = start; i < nc; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { /* add new pivot to dm */ /* for (j = 0; j < i; ++j) { * if (dr[j] != 0) { * printf("dr =/= 0 at pos %u / %u || %u\n", j, i, start); * break; * } * } */ cf32_t *np = dm + i*nc; for (j = i; j < nc; ++j) { dr[j] = dr[j] % mod; np[j] = (cf32_t)dr[j]; } /* normalize new pivot row */ normalize_dense_matrix_row_kernel_ff_32( np, i, nc, fc); pivs[i] = np; return i; } const int64_t mul = (int64_t)dr[i]; const cf32_t *red = pivs[i]; const len_t os = ((nc-i) % 4) + i; /* for (j = 0; j < nc; ++j) { * dr[j] -= mul * red[j]; * dr[j] += (dr[j] >> 63) & mod2; * } */ for (j = i; j < os; ++j) { dr[j] -= mul * red[j]; dr[j] += (dr[j] >> 63) & mod2; } for (; j < nc; j += 4) { dr[j] -= mul * red[j]; dr[j] += (dr[j] >> 63) & mod2; dr[j+1] -= mul * red[j+1]; dr[j+1] += (dr[j+1] >> 63) & mod2; dr[j+2] -= mul * red[j+2]; dr[j+2] += (dr[j+2] >> 63) & mod2; dr[j+3] -= mul * red[j+3]; dr[j+3] += (dr[j+3] >> 63) & mod2; } } return -1; } #endif /* is_kernel_trivial() is unused at the moment */ #if 0 /* If the matrix has size m (rows) x n (columns) with m << n then * we do the following: Generate a dense m x m matrix where the entries * in the mth column is a random linear combination of column entries * m up to n from the correspdoning row. Next we check if the kernel * for this m x m matrix is trivial or not. */ static int is_kernel_trivial( bs_t *sat, hm_t **upivs, /* already sorted by increasing pivot */ const len_t ncl, /* number of columns left, all of them are zero */ const len_t ncr, /* number of columns right */ const md_t * const st ) { len_t i, j; len_t max_col = 0; for (i = 0; i < sat->ld; ++i) { max_col = max_col < sat->hm[i][OFFSET] ? sat->hm[i][OFFSET] : max_col; } int ret = 0; const int64_t fc = st->fc; const int64_t mod2 = (int64_t)fc * fc; /* make a dense matrix first */ const len_t dim = max_col - ncl; /* allocate memory */ cf32_t *dm = (cf32_t *)calloc((unsigned long)(sat->ld*dim), sizeof(cf32_t)); int64_t *dr = (int64_t *)calloc((unsigned long)dim, sizeof(int64_t)); int64_t *mul = (int64_t *)calloc((unsigned long)ncr, sizeof(int64_t)); cf32_t **pivs = (cf32_t **)calloc((unsigned long)dim, sizeof(cf32_t *)); /* fill random value array */ for (i = 0; i < ncr; ++i) { mul[i] = (int64_t)rand() & fc; } for (i = 0; i < sat->ld; ++i) { memset(dr, 0, (unsigned long)dim * sizeof(int64_t)); hm_t *npiv = upivs[i]; const len_t len = upivs[i][LENGTH]; cf32_t *cf = sat->cf_32[npiv[COEFFS]]; hm_t *cols = npiv + OFFSET; j = 0; /* while (j < len) { * dr[cols[j]-ncl] = cf[j]; * j++; * } */ while (j < len && cols[j] < dim+ncl) { dr[cols[j]-ncl] = cf[j]; j++; } while (j < len) { dr[dim-1] -= mul[cols[j]-ncl] * cf[j]; dr[dim-1] += (dr[dim-1] >> 63) & mod2; j++; } ret = reduce_dense_row_by_dense_pivots_ff_32( dr, dm, pivs, cols[0]-ncl, dim, fc); /* dr, dm, pivs, cols[0]-ncl, ncr, fc); */ if (ret == -1) { free(dm); free(dr); free(mul); free(pivs); return 0; } } free(dm); free(dr); free(mul); free(pivs); return 1; } #endif static inline cf32_t *normalize_sparse_matrix_row_ff_32( cf32_t *row, const len_t os, const len_t len, const uint32_t fc ) { len_t i; const uint32_t inv = mod_p_inverse_32(row[0], fc); for (i = 0; i < os; ++i) { row[i] = (cf32_t)(((uint64_t)row[i] * inv) % fc); } /* we need to set i to os since os < 1 is possible */ for (i = os; i < len; i += UNROLL) { row[i] = (cf32_t)(((uint64_t)row[i] * inv) % fc); row[i+1] = (cf32_t)(((uint64_t)row[i+1] * inv) % fc); row[i+2] = (cf32_t)(((uint64_t)row[i+2] * inv) % fc); row[i+3] = (cf32_t)(((uint64_t)row[i+3] * inv) % fc); } row[0] = 1; return row; } static inline cf32_t *adjust_multiplier_sparse_matrix_row_ff_32( cf32_t *row, const cf32_t * const cfs, const len_t os, const len_t len, const uint32_t fc ) { len_t i; const uint32_t inv = mod_p_inverse_32(cfs[0], fc); for (i = 0; i < os; ++i) { row[i] = (cf32_t)(((uint64_t)row[i] * inv) % fc); } /* we need to set i to os since os < 1 is possible */ for (i = os; i < len; i += UNROLL) { row[i] = (cf32_t)(((uint64_t)row[i] * inv) % fc); row[i+1] = (cf32_t)(((uint64_t)row[i+1] * inv) % fc); row[i+2] = (cf32_t)(((uint64_t)row[i+2] * inv) % fc); row[i+3] = (cf32_t)(((uint64_t)row[i+3] * inv) % fc); } return row; } static inline cf32_t *multiply_sparse_matrix_row_ff_32( cf32_t *row, const cf32_t mul, const len_t os, const len_t len, const uint32_t fc ) { len_t i; for (i = 0; i < os; ++i) { row[i] = (cf32_t)(((uint64_t)row[i] * mul) % fc); } /* we need to set i to os since os < 1 is possible */ for (i = os; i < len; i += UNROLL) { row[i] = (cf32_t)(((uint64_t)row[i] * mul) % fc); row[i+1] = (cf32_t)(((uint64_t)row[i+1] * mul) % fc); row[i+2] = (cf32_t)(((uint64_t)row[i+2] * mul) % fc); row[i+3] = (cf32_t)(((uint64_t)row[i+3] * mul) % fc); } return row; } static hm_t *reduce_dense_row_by_known_pivots_sparse_17_bit( int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t * const * const pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const hm_t tmp_pos, /* position of new coeffs array in tmpcf */ const len_t mh, /* multiplier hash for tracing */ const len_t bi, /* basis index of generating element */ const len_t tr, /* trace data? */ md_t *st ) { hi_t i, j, k; hm_t *dts; cf32_t *cfs; int64_t np = -1; const int64_t mod = (int64_t)st->fc; const len_t ncols = mat->nc; const len_t ncl = mat->ncl; cf32_t * const * const mcf = mat->cf_32; rba_t *rba; if (tr > 0) { rba = mat->rba[tmp_pos]; } else { rba = NULL; } #if defined HAVE_AVX512_F int64_t res[8] __attribute__((aligned(64))); __m512i redv, mulv, prodv, drv, resv; #elif defined HAVE_AVX2 int64_t res[4] __attribute__((aligned(32))); __m256i redv, mulv, prodv, drv, resv; #elif defined __aarch64__ uint64_t tmp[2] __attribute__((aligned(32))); uint32x4_t redv; uint64x2_t drv, resv; #endif k = 0; for (i = dpiv; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { np = i; } k++; continue; } /* found reducer row, get multiplier */ const int64_t mul = mod - dr[i]; dts = pivs[i]; printf("found reducer %d\n", i); if (i < ncl) { cfs = bs->cf_32[dts[COEFFS]]; /* set corresponding bit of reducer in reducer bit array */ if (tr > 0) { rba[i/32] |= 1U << (i % 32); } } else { cfs = mcf[dts[COEFFS]]; } #if defined HAVE_AVX512_F const len_t len = dts[LENGTH]; const len_t os = len % 16; const hm_t * const ds = dts + OFFSET; const uint32_t mul32 = (int32_t)(mod - dr[i]); mulv = _mm512_set1_epi32(mul32); for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += 16) { redv = _mm512_loadu_si512((__m512i*)(cfs+j)); drv = _mm512_setr_epi64( dr[ds[j+1]], dr[ds[j+3]], dr[ds[j+5]], dr[ds[j+7]], dr[ds[j+9]], dr[ds[j+11]], dr[ds[j+13]], dr[ds[j+15]]); /* first four mult-adds -- lower */ prodv = _mm512_mul_epu32(mulv, _mm512_srli_epi64(redv, 32)); resv = _mm512_add_epi64(drv, prodv); _mm512_store_si512((__m512*)(res), resv); dr[ds[j+1]] = res[0]; dr[ds[j+3]] = res[1]; dr[ds[j+5]] = res[2]; dr[ds[j+7]] = res[3]; dr[ds[j+9]] = res[4]; dr[ds[j+11]] = res[5]; dr[ds[j+13]] = res[6]; dr[ds[j+15]] = res[7]; /* second four mult-adds -- higher */ prodv = _mm512_mul_epu32(mulv, redv); drv = _mm512_setr_epi64( dr[ds[j]], dr[ds[j+2]], dr[ds[j+4]], dr[ds[j+6]], dr[ds[j+8]], dr[ds[j+10]], dr[ds[j+12]], dr[ds[j+14]]); resv = _mm512_add_epi64(drv, prodv); _mm512_store_si512((__m512i*)(res), resv); dr[ds[j]] = res[0]; dr[ds[j+2]] = res[1]; dr[ds[j+4]] = res[2]; dr[ds[j+6]] = res[3]; dr[ds[j+8]] = res[4]; dr[ds[j+10]] = res[5]; dr[ds[j+12]] = res[6]; dr[ds[j+14]] = res[7]; } #elif defined HAVE_AVX2 const len_t len = dts[LENGTH]; const len_t os = len % 8; const hm_t * const ds = dts + OFFSET; const uint32_t mul32 = (int32_t)(mod - dr[i]); mulv = _mm256_set1_epi32(mul32); for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += 8) { redv = _mm256_lddqu_si256((__m256i*)(cfs+j)); drv = _mm256_setr_epi64x( dr[ds[j+1]], dr[ds[j+3]], dr[ds[j+5]], dr[ds[j+7]]); /* first four mult-adds -- lower */ prodv = _mm256_mul_epu32(mulv, _mm256_srli_epi64(redv, 32)); resv = _mm256_add_epi64(drv, prodv); _mm256_store_si256((__m256i*)(res), resv); dr[ds[j+1]] = res[0]; dr[ds[j+3]] = res[1]; dr[ds[j+5]] = res[2]; dr[ds[j+7]] = res[3]; /* second four mult-adds -- higher */ prodv = _mm256_mul_epu32(mulv, redv); drv = _mm256_setr_epi64x( dr[ds[j]], dr[ds[j+2]], dr[ds[j+4]], dr[ds[j+6]]); resv = _mm256_add_epi64(drv, prodv); _mm256_store_si256((__m256i*)(res), resv); dr[ds[j]] = res[0]; dr[ds[j+2]] = res[1]; dr[ds[j+4]] = res[2]; dr[ds[j+6]] = res[3]; } #elif defined __aarch64__ const len_t len = dts[LENGTH]; const len_t os = len % 16; const hm_t * const ds = dts + OFFSET; const cf32_t mul32 = (cf32_t)(mod - dr[i]); const uint32x2_t mulv = vmov_n_u32(mul32); for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += 16) { tmp[0] = (uint64_t)dr[ds[j]]; tmp[1] = (uint64_t)dr[ds[j+1]]; drv = vld1q_u64(tmp); redv = vld1q_u32((cf32_t *)(cfs)+j); resv = vmlal_u32(drv, vget_low_u32(redv), mulv); vst1q_u64(tmp, resv); dr[ds[j]] = (int64_t)tmp[0]; dr[ds[j+1]] = (int64_t)tmp[1]; tmp[0] = (uint64_t)dr[ds[j+2]]; tmp[1] = (uint64_t)dr[ds[j+3]]; drv = vld1q_u64(tmp); resv = vmlal_u32(drv, vget_high_u32(redv), mulv); vst1q_u64(tmp, resv); dr[ds[j+2]] = (int64_t)tmp[0]; dr[ds[j+3]] = (int64_t)tmp[1]; tmp[0] = (uint64_t)dr[ds[j+4]]; tmp[1] = (uint64_t)dr[ds[j+5]]; drv = vld1q_u64(tmp); redv = vld1q_u32((cf32_t *)(cfs)+j+4); resv = vmlal_u32(drv, vget_low_u32(redv), mulv); vst1q_u64(tmp, resv); dr[ds[j+4]] = (int64_t)tmp[0]; dr[ds[j+5]] = (int64_t)tmp[1]; tmp[0] = (uint64_t)dr[ds[j+6]]; tmp[1] = (uint64_t)dr[ds[j+7]]; drv = vld1q_u64(tmp); resv = vmlal_u32(drv, vget_high_u32(redv), mulv); vst1q_u64(tmp, resv); dr[ds[j+6]] = (int64_t)tmp[0]; dr[ds[j+7]] = (int64_t)tmp[1]; tmp[0] = (uint64_t)dr[ds[j+8]]; tmp[1] = (uint64_t)dr[ds[j+9]]; drv = vld1q_u64(tmp); redv = vld1q_u32((cf32_t *)(cfs)+j+8); resv = vmlal_u32(drv, vget_low_u32(redv), mulv); vst1q_u64(tmp, resv); dr[ds[j+8]] = (int64_t)tmp[0]; dr[ds[j+9]] = (int64_t)tmp[1]; tmp[0] = (uint64_t)dr[ds[j+10]]; tmp[1] = (uint64_t)dr[ds[j+11]]; drv = vld1q_u64(tmp); resv = vmlal_u32(drv, vget_high_u32(redv), mulv); vst1q_u64(tmp, resv); dr[ds[j+10]] = (int64_t)tmp[0]; dr[ds[j+11]] = (int64_t)tmp[1]; tmp[0] = (uint64_t)dr[ds[j+12]]; tmp[1] = (uint64_t)dr[ds[j+13]]; drv = vld1q_u64(tmp); redv = vld1q_u32((cf32_t *)(cfs)+j+12); resv = vmlal_u32(drv, vget_low_u32(redv), mulv); vst1q_u64(tmp, resv); dr[ds[j+12]] = (int64_t)tmp[0]; dr[ds[j+13]] = (int64_t)tmp[1]; tmp[0] = (uint64_t)dr[ds[j+14]]; tmp[1] = (uint64_t)dr[ds[j+15]]; drv = vld1q_u64(tmp); resv = vmlal_u32(drv, vget_high_u32(redv), mulv); vst1q_u64(tmp, resv); dr[ds[j+14]] = (int64_t)tmp[0]; dr[ds[j+15]] = (int64_t)tmp[1]; } #else const len_t os = dts[PRELOOP]; const len_t len = dts[LENGTH]; const hm_t * const ds = dts + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] += mul * cfs[j]; dr[ds[j+1]] += mul * cfs[j+1]; dr[ds[j+2]] += mul * cfs[j+2]; dr[ds[j+3]] += mul * cfs[j+3]; } #endif dr[i] = 0; st->application_nr_mult += len / 1000.0; st->application_nr_add += len / 1000.0; st->application_nr_red++; } if (k == 0) { return NULL; } hm_t *row = (hm_t *)malloc((unsigned long)(k+OFFSET) * sizeof(hm_t)); cf32_t *cf = (cf32_t *)malloc((unsigned long)(k) * sizeof(cf32_t)); j = 0; hm_t *rs = row + OFFSET; for (i = ncl; i < ncols; ++i) { if (dr[i] != 0) { rs[j] = (hm_t)i; cf[j] = (cf32_t)dr[i]; j++; } } row[BINDEX] = bi; row[MULT] = mh; row[COEFFS] = tmp_pos; row[PRELOOP] = j % UNROLL; row[LENGTH] = j; mat->cf_32[tmp_pos] = cf; return row; } static hm_t *trace_reduce_dense_row_by_known_pivots_sparse_17_bit( rba_t *rba, int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t * const * const pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const hm_t tmp_pos, /* position of new coeffs array in tmpcf */ const len_t mh, /* multiplier hash for tracing */ const len_t bi, /* basis index of generating element */ md_t *st ) { hi_t i, j, k; hm_t *dts; cf32_t *cfs; int64_t np = -1; const int64_t mod = (int64_t)st->fc; const len_t ncols = mat->nc; const len_t ncl = mat->ncl; cf32_t * const * const mcf = mat->cf_32; k = 0; for (i = dpiv; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { np = i; } k++; continue; } /* found reducer row, get multiplier */ const int64_t mul = mod - dr[i]; dts = pivs[i]; if (i < ncl) { cfs = bs->cf_32[dts[COEFFS]]; /* set corresponding bit of reducer in reducer bit array */ rba[i/32] |= 1U << (i % 32); } else { cfs = mcf[dts[COEFFS]]; } const len_t os = dts[PRELOOP]; const len_t len = dts[LENGTH]; const hm_t * const ds = dts + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] += mul * cfs[j]; dr[ds[j+1]] += mul * cfs[j+1]; dr[ds[j+2]] += mul * cfs[j+2]; dr[ds[j+3]] += mul * cfs[j+3]; } dr[i] = 0; st->trace_nr_mult += len / 1000.0; st->trace_nr_add += len / 1000.0; st->trace_nr_red++; } hm_t *row = (hm_t *)malloc((unsigned long)(k+OFFSET) * sizeof(hm_t)); cf32_t *cf = (cf32_t *)malloc((unsigned long)(k) * sizeof(cf32_t)); j = 0; hm_t *rs = row + OFFSET; for (i = ncl; i < ncols; ++i) { if (dr[i] != 0) { rs[j] = (hm_t)i; cf[j] = (cf32_t)dr[i]; j++; } } row[BINDEX] = bi; row[MULT] = mh; row[COEFFS] = tmp_pos; row[PRELOOP] = j % UNROLL; row[LENGTH] = j; mat->cf_32[tmp_pos] = cf; return row; } static hm_t *reduce_dense_row_by_known_pivots_sparse_up_to_ff_31_bit( int64_t *dr, bs_t *sat, const bs_t * const bs, hm_t *const *pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const len_t cf_idx, const hm_t tmp_pos, /* position of new coeffs array in tmpcf */ const len_t end, /* column index up to which we reduce */ const len_t ncols, md_t *st ) { hi_t i, j, k; cf32_t *cfs; hm_t *dts; int64_t np = -1; const int64_t mod = (int64_t)st->fc; const int64_t mod2 = (int64_t)st->fc * st->fc; #ifdef HAVE_AVX2 int64_t res[4] __attribute__((aligned(32))); __m256i cmpv, redv, drv, mulv, prodv, resv, rresv; __m256i zerov= _mm256_set1_epi64x(0); __m256i mod2v = _mm256_set1_epi64x(mod2); #endif for (i = dpiv; i < end; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { np = i; } continue; } /* found reducer row, get multiplier */ const int64_t mul = (int64_t)dr[i]; dts = pivs[i]; cfs = bs->cf_32[dts[COEFFS]]; #ifdef HAVE_AVX2 const len_t len = dts[LENGTH]; const len_t os = len % 8; const hm_t * const ds = dts + OFFSET; const uint32_t mul32 = (uint32_t)(dr[i]); mulv = _mm256_set1_epi32(mul32); for (j = 0; j < os; ++j) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; } for (; j < len; j += 8) { redv = _mm256_loadu_si256((__m256i*)(cfs+j)); drv = _mm256_setr_epi64x( dr[ds[j+1]], dr[ds[j+3]], dr[ds[j+5]], dr[ds[j+7]]); /* first four mult-adds -- lower */ prodv = _mm256_mul_epu32(mulv, _mm256_srli_epi64(redv, 32)); resv = _mm256_sub_epi64(drv, prodv); cmpv = _mm256_cmpgt_epi64(zerov, resv); rresv = _mm256_add_epi64(resv, _mm256_and_si256(cmpv, mod2v)); _mm256_store_si256((__m256i*)(res), rresv); dr[ds[j+1]] = res[0]; dr[ds[j+3]] = res[1]; dr[ds[j+5]] = res[2]; dr[ds[j+7]] = res[3]; /* second four mult-adds -- higher */ prodv = _mm256_mul_epu32(mulv, redv); drv = _mm256_setr_epi64x( dr[ds[j]], dr[ds[j+2]], dr[ds[j+4]], dr[ds[j+6]]); resv = _mm256_sub_epi64(drv, prodv); cmpv = _mm256_cmpgt_epi64(zerov, resv); rresv = _mm256_add_epi64(resv, _mm256_and_si256(cmpv, mod2v)); _mm256_store_si256((__m256i*)(res), rresv); dr[ds[j]] = res[0]; dr[ds[j+2]] = res[1]; dr[ds[j+4]] = res[2]; dr[ds[j+6]] = res[3]; } #else const len_t os = dts[PRELOOP]; const len_t len = dts[LENGTH]; const hm_t * const ds = dts + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; } for (; j < len; j += UNROLL) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j+1]] -= mul * cfs[j+1]; dr[ds[j+2]] -= mul * cfs[j+2]; dr[ds[j+3]] -= mul * cfs[j+3]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; dr[ds[j+1]] += (dr[ds[j+1]] >> 63) & mod2; dr[ds[j+2]] += (dr[ds[j+2]] >> 63) & mod2; dr[ds[j+3]] += (dr[ds[j+3]] >> 63) & mod2; } #endif dr[i] = 0; st->application_nr_mult += len / 1000.0; st->application_nr_add += len / 1000.0; st->application_nr_red++; } k = ncols-end; hm_t *row = (hm_t *)malloc((unsigned long)(k+OFFSET) * sizeof(hm_t)); cf32_t *cf = (cf32_t *)malloc((unsigned long)(k) * sizeof(cf32_t)); j = 0; hm_t *rs = row + OFFSET; for (i = end; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] != 0) { rs[j] = (hm_t)i; cf[j] = (cf32_t)dr[i]; j++; } } if (j == 0) { free(row); free(cf); return NULL; } row[COEFFS] = cf_idx; row[PRELOOP] = j % UNROLL; row[LENGTH] = j; row = realloc(row, (unsigned long)(j+OFFSET) * sizeof(hm_t)); cf = realloc(cf, (unsigned long)j * sizeof(cf32_t)); sat->cf_32[cf_idx] = cf; return row; } static hm_t *sba_reduce_dense_row_by_known_pivots_sparse_31_bit( int64_t *dr, smat_t *smat, hm_t *const *pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const hm_t sm, /* signature monomial of row reduced */ const len_t si, /* signature index of row reduced */ const len_t ri, /* index of row in matrix */ md_t *st ) { len_t i, j, k; cf32_t *cfs; hm_t *dts; int32_t fnzc = -1; /* first non zero column */ const int64_t mod = (int64_t)st->fc; const int64_t mod2 = (int64_t)st->fc * st->fc; const len_t nc = smat->nc; #ifdef HAVE_AVX2 int64_t res[4] __attribute__((aligned(32))); __m256i cmpv, redv, drv, mulv, prodv, resv, rresv; __m256i zerov= _mm256_set1_epi64x(0); __m256i mod2v = _mm256_set1_epi64x(mod2); #endif k = 0; for (i = dpiv; i < nc; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { if (fnzc == -1) { if (i == dpiv) { for (j = dpiv; j < nc; ++j) { if (dr[j] != 0) { k++; } } fnzc = i; break; } fnzc = i; } k++; continue; } /* found reducer row, get multiplier */ const int64_t mul = (int64_t)dr[i]; dts = pivs[i]; cfs = smat->cc32[dts[SM_CFS]]; #ifdef HAVE_AVX2 const len_t len = dts[SM_LEN]; const len_t os = len % 8; const hm_t * const ds = dts + SM_OFFSET; const uint32_t mul32 = (uint32_t)(dr[i]); mulv = _mm256_set1_epi32(mul32); for (j = 0; j < os; ++j) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; } for (; j < len; j += 8) { redv = _mm256_loadu_si256((__m256i*)(cfs+j)); drv = _mm256_setr_epi64x( dr[ds[j+1]], dr[ds[j+3]], dr[ds[j+5]], dr[ds[j+7]]); /* first four mult-adds -- lower */ prodv = _mm256_mul_epu32(mulv, _mm256_srli_epi64(redv, 32)); resv = _mm256_sub_epi64(drv, prodv); cmpv = _mm256_cmpgt_epi64(zerov, resv); rresv = _mm256_add_epi64(resv, _mm256_and_si256(cmpv, mod2v)); _mm256_store_si256((__m256i*)(res), rresv); dr[ds[j+1]] = res[0]; dr[ds[j+3]] = res[1]; dr[ds[j+5]] = res[2]; dr[ds[j+7]] = res[3]; /* second four mult-adds -- higher */ prodv = _mm256_mul_epu32(mulv, redv); drv = _mm256_setr_epi64x( dr[ds[j]], dr[ds[j+2]], dr[ds[j+4]], dr[ds[j+6]]); resv = _mm256_sub_epi64(drv, prodv); cmpv = _mm256_cmpgt_epi64(zerov, resv); rresv = _mm256_add_epi64(resv, _mm256_and_si256(cmpv, mod2v)); _mm256_store_si256((__m256i*)(res), rresv); dr[ds[j]] = res[0]; dr[ds[j+2]] = res[1]; dr[ds[j+4]] = res[2]; dr[ds[j+6]] = res[3]; } #else const len_t os = dts[SM_PRE]; const len_t len = dts[SM_LEN]; const hm_t * const ds = dts + SM_OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; } for (; j < len; j += UNROLL) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j+1]] -= mul * cfs[j+1]; dr[ds[j+2]] -= mul * cfs[j+2]; dr[ds[j+3]] -= mul * cfs[j+3]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; dr[ds[j+1]] += (dr[ds[j+1]] >> 63) & mod2; dr[ds[j+2]] += (dr[ds[j+2]] >> 63) & mod2; dr[ds[j+3]] += (dr[ds[j+3]] >> 63) & mod2; } #endif dr[i] = 0; st->application_nr_mult += len / 1000.0; st->application_nr_add += len / 1000.0; st->application_nr_red++; } if (k == 0) { free(smat->cr[ri]); smat->cr[ri] = NULL; return smat->cr[ri]; } /* printf("k %d | ri %u | cr[%u] = %p\n", k, ri, ri, smat->cr[ri]); * printf("%lu\n", (unsigned long)(k+SM_OFFSET)); */ smat->cr[ri] = realloc(smat->cr[ri], (unsigned long)(k+SM_OFFSET) * sizeof(hm_t)); cf32_t *cf = (cf32_t *)malloc((unsigned long)(k) * sizeof(cf32_t)); j = 0; hm_t *rs = smat->cr[ri] + SM_OFFSET; for (i = fnzc; i < nc; ++i) { if (dr[i] != 0) { rs[j] = (hm_t)i; cf[j] = (cf32_t)dr[i]; j++; } } smat->cr[ri][SM_SMON] = sm; smat->cr[ri][SM_SIDX] = si; smat->cr[ri][SM_CFS] = ri; smat->cr[ri][SM_PRE] = j % UNROLL; smat->cr[ri][SM_LEN] = j; smat->cc32[ri] = cf; return smat->cr[ri]; } static hm_t *reduce_dense_row_by_known_pivots_sparse_31_bit( int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t *const *pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const hm_t tmp_pos, /* position of new coeffs array in tmpcf */ const len_t mh, /* multiplier hash for tracing */ const len_t bi, /* basis index of generating element */ const len_t tr, /* trace data? */ md_t *st ) { hi_t i, j, k; cf32_t *cfs; hm_t *dts; int64_t np = -1; const int64_t mod = (int64_t)st->fc; const int64_t mod2 = (int64_t)st->fc * st->fc; const len_t ncols = mat->nc; const len_t ncl = mat->ncl; cf32_t * const * const mcf = mat->cf_32; rba_t *rba; if (tr > 0) { rba = mat->rba[tmp_pos]; } else { rba = NULL; } #if defined HAVE_AVX512_F int64_t res[8] __attribute__((aligned(64))); __m512i redv, drv, mulv, prodv, resv, rresv; __mmask8 cmpv; __m512i zerov = _mm512_set1_epi64(0); __m512i mod2v = _mm512_set1_epi64(mod2); #elif defined HAVE_AVX2 int64_t res[4] __attribute__((aligned(32))); __m256i cmpv, redv, drv, mulv, prodv, resv, rresv; __m256i zerov= _mm256_set1_epi64x(0); __m256i mod2v = _mm256_set1_epi64x(mod2); #elif defined __aarch64__ const int64x2_t mod2v = vmovq_n_s64(mod2); int64_t tmp[2] __attribute__((aligned(32))); int32x4_t redv; int64x2_t drv, mask, resv; #endif k = 0; for (i = dpiv; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { np = i; } k++; continue; } /* found reducer row, get multiplier */ const int64_t mul = (int64_t)dr[i]; dts = pivs[i]; if (i < ncl) { /* cfs = bs->cf_32[dts[COEFFS]]; */ /* set corresponding bit of reducer in reducer bit array */ if (tr > 0) { rba[i/32] |= 1U << (i % 32); } } cfs = mcf[dts[COEFFS]]; #if defined HAVE_AVX512_F const len_t len = dts[LENGTH]; const len_t os = len % 16; const hm_t * const ds = dts + OFFSET; const uint32_t mul32 = (int32_t)(dr[i]); mulv = _mm512_set1_epi32(mul32); for (j = 0; j < os; ++j) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; } for (; j < len; j += 16) { redv = _mm512_loadu_si512((__m512i*)(cfs+j)); drv = _mm512_setr_epi64( dr[ds[j+1]], dr[ds[j+3]], dr[ds[j+5]], dr[ds[j+7]], dr[ds[j+9]], dr[ds[j+11]], dr[ds[j+13]], dr[ds[j+15]]); /* first four mult-adds -- lower */ prodv = _mm512_mul_epu32(mulv, _mm512_srli_epi64(redv, 32)); resv = _mm512_sub_epi64(drv, prodv); cmpv = _mm512_cmpgt_epi64_mask(zerov, resv); rresv = _mm512_mask_add_epi64(resv, cmpv, resv, mod2v); _mm512_store_si512((__m512*)(res), rresv); dr[ds[j+1]] = res[0]; dr[ds[j+3]] = res[1]; dr[ds[j+5]] = res[2]; dr[ds[j+7]] = res[3]; dr[ds[j+9]] = res[4]; dr[ds[j+11]] = res[5]; dr[ds[j+13]] = res[6]; dr[ds[j+15]] = res[7]; /* second four mult-adds -- higher */ prodv = _mm512_mul_epu32(mulv, redv); drv = _mm512_setr_epi64( dr[ds[j]], dr[ds[j+2]], dr[ds[j+4]], dr[ds[j+6]], dr[ds[j+8]], dr[ds[j+10]], dr[ds[j+12]], dr[ds[j+14]]); resv = _mm512_sub_epi64(drv, prodv); cmpv = _mm512_cmpgt_epi64_mask(zerov, resv); rresv = _mm512_mask_add_epi64(resv, cmpv, resv, mod2v); _mm512_store_si512((__m512i*)(res), rresv); dr[ds[j]] = res[0]; dr[ds[j+2]] = res[1]; dr[ds[j+4]] = res[2]; dr[ds[j+6]] = res[3]; dr[ds[j+8]] = res[4]; dr[ds[j+10]] = res[5]; dr[ds[j+12]] = res[6]; dr[ds[j+14]] = res[7]; } #elif defined HAVE_AVX2 const len_t len = dts[LENGTH]; const len_t os = len % 8; const hm_t * const ds = dts + OFFSET; const uint32_t mul32 = (uint32_t)(dr[i]); mulv = _mm256_set1_epi32(mul32); for (j = 0; j < os; ++j) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; } for (; j < len; j += 8) { redv = _mm256_loadu_si256((__m256i*)(cfs+j)); drv = _mm256_setr_epi64x( dr[ds[j+1]], dr[ds[j+3]], dr[ds[j+5]], dr[ds[j+7]]); /* first four mult-adds -- lower */ prodv = _mm256_mul_epu32(mulv, _mm256_srli_epi64(redv, 32)); resv = _mm256_sub_epi64(drv, prodv); cmpv = _mm256_cmpgt_epi64(zerov, resv); rresv = _mm256_add_epi64(resv, _mm256_and_si256(cmpv, mod2v)); _mm256_store_si256((__m256i*)(res), rresv); dr[ds[j+1]] = res[0]; dr[ds[j+3]] = res[1]; dr[ds[j+5]] = res[2]; dr[ds[j+7]] = res[3]; /* second four mult-adds -- higher */ prodv = _mm256_mul_epu32(mulv, redv); drv = _mm256_setr_epi64x( dr[ds[j]], dr[ds[j+2]], dr[ds[j+4]], dr[ds[j+6]]); resv = _mm256_sub_epi64(drv, prodv); cmpv = _mm256_cmpgt_epi64(zerov, resv); rresv = _mm256_add_epi64(resv, _mm256_and_si256(cmpv, mod2v)); _mm256_store_si256((__m256i*)(res), rresv); dr[ds[j]] = res[0]; dr[ds[j+2]] = res[1]; dr[ds[j+4]] = res[2]; dr[ds[j+6]] = res[3]; } #elif defined __aarch64__ const len_t len = dts[LENGTH]; const len_t os = len % 8; const hm_t * const ds = dts + OFFSET; const int32_t mul32 = (int32_t)(dr[i]); const int32x2_t mulv = vmov_n_s32(mul32); for (j = 0; j < os; ++j) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; } for (; j < len; j += 8) { tmp[0] = dr[ds[j]]; tmp[1] = dr[ds[j+1]]; drv = vld1q_s64(tmp); redv = vld1q_s32((int32_t *)(cfs)+j); /* multiply and subtract */ resv = vmlsl_s32(drv, vget_low_s32(redv), mulv); mask = vreinterpretq_s64_u64(vcltzq_s64(resv)); resv = vaddq_s64(resv, vandq_s64(mask, mod2v)); vst1q_s64(tmp, resv); dr[ds[j]] = tmp[0]; dr[ds[j+1]] = tmp[1]; tmp[0] = dr[ds[j+2]]; tmp[1] = dr[ds[j+3]]; drv = vld1q_s64(tmp); resv = vmlsl_s32(drv, vget_high_s32(redv), mulv); mask = vreinterpretq_s64_u64(vcltzq_s64(resv)); resv = vaddq_s64(resv, vandq_s64(mask, mod2v)); vst1q_s64(tmp, resv); dr[ds[j+2]] = tmp[0]; dr[ds[j+3]] = tmp[1]; tmp[0] = dr[ds[j+4]]; tmp[1] = dr[ds[j+5]]; drv = vld1q_s64(tmp); redv = vld1q_s32((int32_t *)(cfs)+j+4); /* multiply and subtract */ resv = vmlsl_s32(drv, vget_low_s32(redv), mulv); mask = vreinterpretq_s64_u64(vcltzq_s64(resv)); resv = vaddq_s64(resv, vandq_s64(mask, mod2v)); vst1q_s64(tmp, resv); dr[ds[j+4]] = tmp[0]; dr[ds[j+5]] = tmp[1]; tmp[0] = dr[ds[j+6]]; tmp[1] = dr[ds[j+7]]; drv = vld1q_s64(tmp); resv = vmlsl_s32(drv, vget_high_s32(redv), mulv); mask = vreinterpretq_s64_u64(vcltzq_s64(resv)); resv = vaddq_s64(resv, vandq_s64(mask, mod2v)); vst1q_s64(tmp, resv); dr[ds[j+6]] = tmp[0]; dr[ds[j+7]] = tmp[1]; } #else const len_t os = dts[PRELOOP]; const len_t len = dts[LENGTH]; const hm_t * const ds = dts + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; } for (; j < len; j += UNROLL) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j+1]] -= mul * cfs[j+1]; dr[ds[j+2]] -= mul * cfs[j+2]; dr[ds[j+3]] -= mul * cfs[j+3]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; dr[ds[j+1]] += (dr[ds[j+1]] >> 63) & mod2; dr[ds[j+2]] += (dr[ds[j+2]] >> 63) & mod2; dr[ds[j+3]] += (dr[ds[j+3]] >> 63) & mod2; } #endif dr[i] = 0; st->application_nr_mult += len / 1000.0; st->application_nr_add += len / 1000.0; st->application_nr_red++; } if (k == 0) { return NULL; } hm_t *row = (hm_t *)malloc((unsigned long)(k+OFFSET) * sizeof(hm_t)); cf32_t *cf = (cf32_t *)malloc((unsigned long)(k) * sizeof(cf32_t)); j = 0; hm_t *rs = row + OFFSET; for (i = ncl; i < ncols; ++i) { if (dr[i] != 0) { rs[j] = (hm_t)i; cf[j] = (cf32_t)dr[i]; j++; } } row[BINDEX] = bi; row[MULT] = mh; row[COEFFS] = tmp_pos; row[PRELOOP] = j % UNROLL; row[LENGTH] = j; mat->cf_32[tmp_pos] = cf; return row; } static hm_t *reduce_dense_row_by_known_pivots_sparse_sat_ff_31_bit( int64_t *dr, int64_t *drm, cf32_t **pivcf, hm_t **mulh, cf32_t **mulcf, hm_t *const *pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const hm_t tmp_pos, /* position of new coeffs arrays */ const len_t sat_ld, /* number of current multipliers */ const len_t ncols, /* number of columns */ md_t *st, const len_t ncl ) { hi_t i, j, k; cf32_t *cfs, *cfsm; hm_t *dts, *dtsm; int64_t np = -1; const int64_t mod = (int64_t)st->fc; const int64_t mod2 = (int64_t)st->fc * st->fc; #ifdef HAVE_AVX2 int64_t res[4] __attribute__((aligned(32))); __m256i cmpv, redv, drv, mulv, prodv, resv, rresv; __m256i zerov= _mm256_set1_epi64x(0); __m256i mod2v = _mm256_set1_epi64x(mod2); #endif k = 0; for (i = dpiv; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { np = i; } k++; break; } /* found reducer row, get multiplier */ const int64_t mul = (int64_t)dr[i]; dts = pivs[i]; dtsm = mulh[dts[MULT]]; cfsm = mulcf[dtsm[COEFFS]]; cfs = pivcf[dts[COEFFS]]; #ifdef HAVE_AVX2 const len_t len = dts[LENGTH]; const len_t os = len % 8; const hm_t * const ds = dts + OFFSET; const uint32_t mul32 = (uint32_t)(dr[i]); mulv = _mm256_set1_epi32(mul32); for (j = 0; j < os; ++j) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; } for (; j < len; j += 8) { redv = _mm256_loadu_si256((__m256i*)(cfs+j)); drv = _mm256_setr_epi64x( dr[ds[j+1]], dr[ds[j+3]], dr[ds[j+5]], dr[ds[j+7]]); /* first four mult-adds -- lower */ prodv = _mm256_mul_epu32(mulv, _mm256_srli_epi64(redv, 32)); resv = _mm256_sub_epi64(drv, prodv); cmpv = _mm256_cmpgt_epi64(zerov, resv); rresv = _mm256_add_epi64(resv, _mm256_and_si256(cmpv, mod2v)); _mm256_store_si256((__m256i*)(res), rresv); dr[ds[j+1]] = res[0]; dr[ds[j+3]] = res[1]; dr[ds[j+5]] = res[2]; dr[ds[j+7]] = res[3]; /* second four mult-adds -- higher */ prodv = _mm256_mul_epu32(mulv, redv); drv = _mm256_setr_epi64x( dr[ds[j]], dr[ds[j+2]], dr[ds[j+4]], dr[ds[j+6]]); resv = _mm256_sub_epi64(drv, prodv); cmpv = _mm256_cmpgt_epi64(zerov, resv); rresv = _mm256_add_epi64(resv, _mm256_and_si256(cmpv, mod2v)); _mm256_store_si256((__m256i*)(res), rresv); dr[ds[j]] = res[0]; dr[ds[j+2]] = res[1]; dr[ds[j+4]] = res[2]; dr[ds[j+6]] = res[3]; } const len_t lenm = dtsm[LENGTH]; const len_t osm = lenm % 8; const hm_t * const dsm = dtsm + OFFSET; /* const uint32_t mulm32 = (uint32_t)(drm[i]); */ mulv = _mm256_set1_epi32(mul32); for (j = 0; j < osm; ++j) { drm[dsm[j]] -= mul * cfsm[j]; drm[dsm[j]] += (drm[dsm[j]] >> 63) & mod2; } for (; j < lenm; j += 8) { redv = _mm256_loadu_si256((__m256i*)(cfsm+j)); drv = _mm256_setr_epi64x( drm[dsm[j+1]], drm[dsm[j+3]], drm[dsm[j+5]], drm[dsm[j+7]]); /* first four mult-adds -- lower */ prodv = _mm256_mul_epu32(mulv, _mm256_srli_epi64(redv, 32)); resv = _mm256_sub_epi64(drv, prodv); cmpv = _mm256_cmpgt_epi64(zerov, resv); rresv = _mm256_add_epi64(resv, _mm256_and_si256(cmpv, mod2v)); _mm256_store_si256((__m256i*)(res), rresv); drm[dsm[j+1]] = res[0]; drm[dsm[j+3]] = res[1]; drm[dsm[j+5]] = res[2]; drm[dsm[j+7]] = res[3]; /* second four mult-adds -- higher */ prodv = _mm256_mul_epu32(mulv, redv); drv = _mm256_setr_epi64x( drm[dsm[j]], drm[dsm[j+2]], drm[dsm[j+4]], drm[dsm[j+6]]); resv = _mm256_sub_epi64(drv, prodv); cmpv = _mm256_cmpgt_epi64(zerov, resv); rresv = _mm256_add_epi64(resv, _mm256_and_si256(cmpv, mod2v)); _mm256_store_si256((__m256i*)(res), rresv); drm[dsm[j]] = res[0]; drm[dsm[j+2]] = res[1]; drm[dsm[j+4]] = res[2]; drm[dsm[j+6]] = res[3]; } #else const len_t os = dts[PRELOOP]; const len_t len = dts[LENGTH]; const hm_t * const ds = dts + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; } for (; j < len; j += UNROLL) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j+1]] -= mul * cfs[j+1]; dr[ds[j+2]] -= mul * cfs[j+2]; dr[ds[j+3]] -= mul * cfs[j+3]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; dr[ds[j+1]] += (dr[ds[j+1]] >> 63) & mod2; dr[ds[j+2]] += (dr[ds[j+2]] >> 63) & mod2; dr[ds[j+3]] += (dr[ds[j+3]] >> 63) & mod2; } const len_t osm = dtsm[PRELOOP]; const len_t lenm = dtsm[LENGTH]; const hm_t * const dsm = dtsm + OFFSET; for (j = 0; j < osm; ++j) { drm[dsm[j]] -= mul * cfsm[j]; drm[dsm[j]] += (drm[dsm[j]] >> 63) & mod2; } for (; j < lenm; j += UNROLL) { drm[dsm[j]] -= mul * cfsm[j]; drm[dsm[j+1]] -= mul * cfsm[j+1]; drm[dsm[j+2]] -= mul * cfsm[j+2]; drm[dsm[j+3]] -= mul * cfsm[j+3]; drm[dsm[j]] += (drm[dsm[j]] >> 63) & mod2; drm[dsm[j+1]] += (drm[dsm[j+1]] >> 63) & mod2; drm[dsm[j+2]] += (drm[dsm[j+2]] >> 63) & mod2; drm[dsm[j+3]] += (drm[dsm[j+3]] >> 63) & mod2; } #endif dr[i] = 0; st->application_nr_mult += len / 1000.0; st->application_nr_add += len / 1000.0; st->application_nr_red++; } /* we always have to write the multiplier entry for the kernel * construction, especially if we computed a zero row. */ mulh[tmp_pos] = (hm_t *)malloc((unsigned long)(sat_ld+OFFSET) * sizeof(hm_t)); mulcf[tmp_pos] = (cf32_t *)malloc((unsigned long)(sat_ld) * sizeof(cf32_t)); j = 0; hm_t *rsm = mulh[tmp_pos] + OFFSET; cf32_t*cfm = mulcf[tmp_pos]; for (i = 0; i < sat_ld; ++i) { if (drm[i] != 0) { drm[i] = drm[i] % mod; if (drm[i] != 0) { rsm[j] = (hm_t)i; cfm[j] = (cf32_t)drm[i]; j++; } } } mulh[tmp_pos][PRELOOP] = j % UNROLL; mulh[tmp_pos][LENGTH] = j; mulh[tmp_pos][COEFFS] = tmp_pos; mulh[tmp_pos] = realloc(mulh[tmp_pos], (unsigned long)(j+OFFSET) * sizeof(hm_t)); mulcf[tmp_pos] = realloc(mulcf[tmp_pos], (unsigned long)j * sizeof(cf32_t)); if (k == 0) { return NULL; } k = ncols - np; hm_t *row = (hm_t *)malloc((unsigned long)(k+OFFSET) * sizeof(hm_t)); cf32_t *cf = (cf32_t *)malloc((unsigned long)(k) * sizeof(cf32_t)); j = 0; hm_t *rs = row + OFFSET; for (i = np; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] != 0) { rs[j] = (hm_t)i; cf[j] = (cf32_t)dr[i]; j++; } } row[COEFFS] = tmp_pos; row[PRELOOP] = j % UNROLL; row[LENGTH] = j; row[MULT] = tmp_pos; pivcf[tmp_pos] = cf; return row; } static hm_t *trace_reduce_dense_row_by_known_pivots_sparse_31_bit( rba_t *rba, int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t *const *pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const hm_t tmp_pos, /* position of new coeffs array in tmpcf */ const len_t mh, /* multiplier hash for tracing */ const len_t bi, /* basis index of generating element */ md_t *st ) { hi_t i, j, k; cf32_t *cfs; hm_t *dts; int64_t np = -1; const int64_t mod = (int64_t)st->fc; const int64_t mod2 = (int64_t)st->fc * st->fc; const len_t ncols = mat->nc; const len_t ncl = mat->ncl; cf32_t * const * const mcf = mat->cf_32; #ifdef HAVE_AVX2 int64_t res[4] __attribute__((aligned(32))); __m256i cmpv, redv, drv, mulv, prodv, resv, rresv; __m256i zerov = _mm256_set1_epi64x(0); __m256i mod2v = _mm256_set1_epi64x(mod2); #endif k = 0; for (i = dpiv; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { np = i; } k++; continue; } /* found reducer row, get multiplier */ const int64_t mul = (int64_t)dr[i]; dts = pivs[i]; if (i < ncl) { cfs = bs->cf_32[dts[COEFFS]]; /* set corresponding bit of reducer in reducer bit array */ rba[i/32] |= 1U << (i % 32); } else { cfs = mcf[dts[COEFFS]]; } #ifdef HAVE_AVX2 const len_t len = dts[LENGTH]; const len_t os = len % 8; const hm_t * const ds = dts + OFFSET; const uint32_t mul32 = (uint32_t)(dr[i]); mulv = _mm256_set1_epi32(mul32); for (j = 0; j < os; ++j) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; } for (; j < len; j += 8) { redv = _mm256_loadu_si256((__m256i*)(cfs+j)); drv = _mm256_setr_epi64x( dr[ds[j+1]], dr[ds[j+3]], dr[ds[j+5]], dr[ds[j+7]]); /* first four mult-adds -- lower */ prodv = _mm256_mul_epu32(mulv, _mm256_srli_epi64(redv, 32)); resv = _mm256_sub_epi64(drv, prodv); cmpv = _mm256_cmpgt_epi64(zerov, resv); rresv = _mm256_add_epi64(resv, _mm256_and_si256(cmpv, mod2v)); _mm256_store_si256((__m256i*)(res), rresv); dr[ds[j+1]] = res[0]; dr[ds[j+3]] = res[1]; dr[ds[j+5]] = res[2]; dr[ds[j+7]] = res[3]; /* second four mult-adds -- higher */ prodv = _mm256_mul_epu32(mulv, redv); drv = _mm256_setr_epi64x( dr[ds[j]], dr[ds[j+2]], dr[ds[j+4]], dr[ds[j+6]]); resv = _mm256_sub_epi64(drv, prodv); cmpv = _mm256_cmpgt_epi64(zerov, resv); rresv = _mm256_add_epi64(resv, _mm256_and_si256(cmpv, mod2v)); _mm256_store_si256((__m256i*)(res), rresv); dr[ds[j]] = res[0]; dr[ds[j+2]] = res[1]; dr[ds[j+4]] = res[2]; dr[ds[j+6]] = res[3]; } #else const len_t os = dts[PRELOOP]; const len_t len = dts[LENGTH]; const hm_t * const ds = dts + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; } for (; j < len; j += UNROLL) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j+1]] -= mul * cfs[j+1]; dr[ds[j+2]] -= mul * cfs[j+2]; dr[ds[j+3]] -= mul * cfs[j+3]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; dr[ds[j+1]] += (dr[ds[j+1]] >> 63) & mod2; dr[ds[j+2]] += (dr[ds[j+2]] >> 63) & mod2; dr[ds[j+3]] += (dr[ds[j+3]] >> 63) & mod2; } #endif dr[i] = 0; st->trace_nr_mult += len / 1000.0; st->trace_nr_add += len / 1000.0; st->trace_nr_red++; } if (k == 0) { return NULL; } hm_t *row = (hm_t *)malloc((unsigned long)(k+OFFSET) * sizeof(hm_t)); cf32_t *cf = (cf32_t *)malloc((unsigned long)(k) * sizeof(cf32_t)); j = 0; hm_t *rs = row + OFFSET; for (i = ncl; i < ncols; ++i) { if (dr[i] != 0) { rs[j] = (hm_t)i; cf[j] = (cf32_t)dr[i]; j++; } } row[BINDEX] = bi; row[MULT] = mh; row[COEFFS] = tmp_pos; row[PRELOOP] = j % UNROLL; row[LENGTH] = j; mat->cf_32[tmp_pos] = cf; return row; } static hm_t *reduce_dense_row_by_known_pivots_sparse_32_bit( int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t *const *pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const hm_t tmp_pos, /* position of new coeffs array in tmpcf */ const len_t mh, /* multiplier hash for tracing */ const len_t bi, /* basis index of generating element */ const len_t tr, /* trace data? */ md_t *st ) { hi_t i, j, k; cf32_t *cfs; hm_t *dts; int64_t np = -1; const uint64_t mod = (uint64_t)st->fc; const len_t ncols = mat->nc; const len_t ncl = mat->ncl; cf32_t * const * const mcf = mat->cf_32; rba_t *rba; if (tr > 0) { rba = mat->rba[tmp_pos]; } else { rba = NULL; } const uint64_t mask = (uint32_t)0xFFFFFFFF; uint64_t RED_32 = ((uint64_t)2<<31) % st->fc; uint64_t RED_64 = ((uint64_t)1<<63) % st->fc; RED_64 = (RED_64*2) % st->fc; uint64_t drlow[ncols]; uint64_t drhigh[ncols]; uint64_t udr[ncols]; uint64_t prod; for (i = 0; i < ncols; ++i) { drlow[i] = dr[i] & mask; drhigh[i] = dr[i] >> 32; } k = 0; for (i = dpiv; i < ncols; ++i) { udr[i] = ((drhigh[i] >> 32) * RED_64) % mod; udr[i] += ((drhigh[i] & (uint64_t)0xFFFFFFFF) * RED_32) % mod; udr[i] += drlow[i]; udr[i] %= mod; if (udr[i] == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { np = i; } k++; continue; } /* found reducer row, get multiplier */ const uint64_t mul = mod-udr[i]; dts = pivs[i]; if (i < ncl) { cfs = bs->cf_32[dts[COEFFS]]; /* set corresponding bit of reducer in reducer bit array */ if (tr > 0) { rba[i/32] |= 1U << (i % 32); } } else { cfs = mcf[dts[COEFFS]]; } const len_t len = dts[LENGTH]; const hm_t * const ds = dts + OFFSET; /* loop unrolling is slower */ for (j = 0; j < len; ++j) { prod = mul * cfs[j]; drhigh[ds[j]] += prod >> 32; drlow[ds[j]] += (prod & mask); } udr[i] = 0; st->application_nr_mult += len / 1000.0; st->application_nr_add += len / 1000.0; st->application_nr_red++; } if (k == 0) { return NULL; } hm_t *row = (hm_t *)malloc((unsigned long)(k+OFFSET) * sizeof(hm_t)); cf32_t *cf = (cf32_t *)malloc((unsigned long)(k) * sizeof(cf32_t)); j = 0; hm_t *rs = row + OFFSET; for (i = np; i < ncols; ++i) { if (udr[i] != 0) { rs[j] = (hm_t)i; cf[j] = (cf32_t)udr[i]; j++; } } row[BINDEX] = bi; row[MULT] = mh; row[COEFFS] = tmp_pos; row[PRELOOP] = j % UNROLL; row[LENGTH] = j; mat->cf_32[tmp_pos] = cf; return row; } static hm_t *trace_reduce_dense_row_by_known_pivots_sparse_32_bit( rba_t *rba, int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t *const *pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const hm_t tmp_pos, /* position of new coeffs array in tmpcf */ const len_t mh, /* multiplier hash for tracing */ const len_t bi, /* basis index of generating element */ md_t *st ) { hi_t i, j, k; cf32_t *cfs; hm_t *dts; int64_t np = -1; const uint64_t mod = (uint64_t)st->fc; const len_t ncols = mat->nc; const len_t ncl = mat->ncl; cf32_t * const * const mcf = mat->cf_32; const uint64_t mask = (uint32_t)0xFFFFFFFF; uint64_t RED_32 = ((uint64_t)2<<31) % st->fc; uint64_t RED_64 = ((uint64_t)1<<63) % st->fc; RED_64 = (RED_64*2) % st->fc; uint64_t drlow[ncols]; uint64_t drhigh[ncols]; uint64_t udr[ncols]; uint64_t prod; for (i = 0; i < ncols; ++i) { drlow[i] = dr[i] & mask; drhigh[i] = dr[i] >> 32; } k = 0; for (i = dpiv; i < ncols; ++i) { udr[i] = ((drhigh[i] >> 32) * RED_64) % mod; udr[i] += ((drhigh[i] & (uint64_t)0xFFFFFFFF) * RED_32) % mod; udr[i] += drlow[i]; udr[i] %= mod; if (udr[i] == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { np = i; } k++; continue; } /* found reducer row, get multiplier */ const uint64_t mul = mod-udr[i]; dts = pivs[i]; if (i < ncl) { cfs = bs->cf_32[dts[COEFFS]]; } else { cfs = mcf[dts[COEFFS]]; } const len_t len = dts[LENGTH]; const hm_t * const ds = dts + OFFSET; /* loop unrolling is slower */ for (j = 0; j < len; ++j) { prod = mul * cfs[j]; drhigh[ds[j]] += prod >> 32; drlow[ds[j]] += (prod & mask); } udr[i] = 0; st->trace_nr_mult += len / 1000.0; st->trace_nr_add += len / 1000.0; st->trace_nr_red++; } if (k == 0) { return NULL; } hm_t *row = (hm_t *)malloc((unsigned long)(k+OFFSET) * sizeof(hm_t)); cf32_t *cf = (cf32_t *)malloc((unsigned long)(k) * sizeof(cf32_t)); j = 0; hm_t *rs = row + OFFSET; for (i = np; i < ncols; ++i) { if (udr[i] != 0) { rs[j] = (hm_t)i; cf[j] = (cf32_t)udr[i]; j++; } } row[BINDEX] = bi; row[MULT] = mh; row[COEFFS] = tmp_pos; row[PRELOOP] = j % UNROLL; row[LENGTH] = j; mat->cf_32[tmp_pos] = cf; return row; } static cf32_t *reduce_dense_row_by_all_pivots_17_bit( int64_t *dr, mat_t *mat, const bs_t * const bs, len_t *pc, hm_t *const * const pivs, cf32_t *const * const dpivs, const uint32_t fc ) { hi_t i, j, k, l; const int64_t mod = (int64_t)fc; len_t np = -1; cf32_t *red; const len_t ncl = mat->ncl; const len_t ncols = mat->nc; /* step 1: reduce by sparse known pivots */ for (i = *pc; i < ncl; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { continue; } /* found reducer row, get multiplier */ const int64_t mul = mod - dr[i]; const cf32_t *cfs = bs->cf_32[pivs[i][COEFFS]]; const len_t os = pivs[i][PRELOOP]; const len_t len = pivs[i][LENGTH]; const hm_t * const ds = pivs[i] + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] += mul * cfs[j]; dr[ds[j+1]] += mul * cfs[j+1]; dr[ds[j+2]] += mul * cfs[j+2]; dr[ds[j+3]] += mul * cfs[j+3]; } dr[i] = 0; } k = 0; /* step 2: reduce by new dense pivots */ for (i = ncl; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (dpivs[i-ncl] == NULL) { if (np == -1) { np = i; } k++; continue; } red = dpivs[i-ncl]; const int64_t mul = mod - dr[i]; const len_t os = (ncols - i) % UNROLL; for (l = 0, j = i; l < os; ++l, ++j) { dr[j] += mul * red[l]; } for (; j < ncols; l += UNROLL, j += UNROLL) { dr[j] += mul * red[l]; dr[j+1] += mul * red[l+1]; dr[j+2] += mul * red[l+2]; dr[j+3] += mul * red[l+3]; } } if (k == 0) { *pc = -1; return NULL; } cf32_t *row = (cf32_t *)calloc((unsigned long)(ncols-np), sizeof(cf32_t)); for (i = np; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } row[i-np] = (cf32_t)dr[i]; } if (row[0] != 1) { row = normalize_dense_matrix_row_ff_32(row, ncols-np, fc); } *pc = np - ncl; return row; } static cf32_t *reduce_dense_row_by_all_pivots_31_bit( int64_t *dr, mat_t *mat, const bs_t * const bs, len_t *pc, hm_t * const * const pivs, cf32_t * const * const dpivs, const uint32_t fc ) { hi_t i, j, k, l; const int64_t mod = (int64_t)fc; const int64_t mod2 = (int64_t)fc * fc; len_t np = -1; cf32_t *red; const len_t ncl = mat->ncl; const len_t ncols = mat->nc; /* step 1: reduce by sparse known pivots */ for (i = *pc; i < ncl; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { continue; } /* found reducer row, get multiplier */ const int64_t mul = (int64_t)dr[i]; const cf32_t *cfs = bs->cf_32[pivs[i][COEFFS]]; const len_t os = pivs[i][PRELOOP]; const len_t len = pivs[i][LENGTH]; const hm_t * const ds = pivs[i] + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; } for (; j < len; j += UNROLL) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j+1]] -= mul * cfs[j+1]; dr[ds[j+2]] -= mul * cfs[j+2]; dr[ds[j+3]] -= mul * cfs[j+3]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; dr[ds[j+1]] += (dr[ds[j+1]] >> 63) & mod2; dr[ds[j+2]] += (dr[ds[j+2]] >> 63) & mod2; dr[ds[j+3]] += (dr[ds[j+3]] >> 63) & mod2; } dr[i] = 0; } k = 0; /* step 2: reduce by new dense pivots */ for (i = ncl; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (dpivs[i-ncl] == NULL) { if (np == -1) { np = i; } k++; continue; } red = dpivs[i-ncl]; const int64_t mul = (int64_t) dr[i]; const len_t os = (ncols - i) % UNROLL; for (l = 0, j = i; l < os; ++l, ++j) { dr[j] -= mul * red[l]; dr[j] += (dr[j] >> 63) & mod2; } for (; j < ncols; l+=4, j += UNROLL) { dr[j] -= mul * red[l]; dr[j+1] -= mul * red[l+1]; dr[j+2] -= mul * red[l+2]; dr[j+3] -= mul * red[l+3]; dr[j] += (dr[j] >> 63) & mod2; dr[j+1] += (dr[j+1] >> 63) & mod2; dr[j+2] += (dr[j+2] >> 63) & mod2; dr[j+3] += (dr[j+3] >> 63) & mod2; } } if (k == 0) { *pc = -1; return NULL; } cf32_t *row = (cf32_t *)calloc((unsigned long)(ncols-np), sizeof(cf32_t)); for (i = np; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } row[i-np] = (cf32_t)dr[i]; } if (row[0] != 1) { row = normalize_dense_matrix_row_ff_32(row, ncols-np, fc); } *pc = np - ncl; return row; } static cf32_t *reduce_dense_row_by_old_pivots_17_bit( int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t *const * const pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const uint32_t fc ) { hi_t i, j; const int64_t mod = (int64_t)fc; const len_t ncols = mat->nc; const len_t ncl = mat->ncl; const len_t ncr = mat->ncr; for (i = dpiv; i < ncl; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { continue; } /* found reducer row, get multiplier */ const int64_t mul = mod - dr[i]; const cf32_t *cfs = bs->cf_32[pivs[i][COEFFS]]; const len_t os = pivs[i][PRELOOP]; const len_t len = pivs[i][LENGTH]; const hm_t * const ds = pivs[i] + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] += mul * cfs[j]; dr[ds[j+1]] += mul * cfs[j+1]; dr[ds[j+2]] += mul * cfs[j+2]; dr[ds[j+3]] += mul * cfs[j+3]; } dr[i] = 0; } /* store a dense row for further dense gaussian elimination */ cf32_t *row = (cf32_t *)calloc( (unsigned long)(ncr), sizeof(cf32_t)); j = 0; for (i = ncl; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; if (dr[i] != 0) { j++; row[i-ncl] = (cf32_t)dr[i]; } } } if (j == 0) { free(row); row = NULL; } return row; } static cf32_t *reduce_dense_row_by_old_pivots_31_bit( int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t *const *pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const uint32_t fc ) { hi_t i, j; const int64_t mod = (int64_t)fc; const int64_t mod2 = (int64_t)fc * fc; const len_t ncols = mat->nc; const len_t ncl = mat->ncl; const len_t ncr = mat->ncr; for (i = dpiv; i < ncl; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { continue; } /* found reducer row, get multiplier */ const int64_t mul = (int64_t)dr[i]; const cf32_t *cfs = bs->cf_32[pivs[i][COEFFS]]; const len_t os = pivs[i][PRELOOP]; const len_t len = pivs[i][LENGTH]; const hm_t * const ds = pivs[i] + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; } for (; j < len; j += UNROLL) { dr[ds[j]] -= mul * cfs[j]; dr[ds[j+1]] -= mul * cfs[j+1]; dr[ds[j+2]] -= mul * cfs[j+2]; dr[ds[j+3]] -= mul * cfs[j+3]; dr[ds[j]] += (dr[ds[j]] >> 63) & mod2; dr[ds[j+1]] += (dr[ds[j+1]] >> 63) & mod2; dr[ds[j+2]] += (dr[ds[j+2]] >> 63) & mod2; dr[ds[j+3]] += (dr[ds[j+3]] >> 63) & mod2; } dr[i] = 0; } /* store a dense row for further dense gaussian elimination */ cf32_t *row = (cf32_t *)calloc( (unsigned long)(ncr), sizeof(cf32_t)); j = 0; for (i = ncl; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; if (dr[i] != 0) { j++; row[i-ncl] = (cf32_t)dr[i]; } } } if (j == 0) { free(row); row = NULL; } return row; } static cf32_t *reduce_dense_row_by_dense_new_pivots_17_bit( int64_t *dr, len_t *pc, cf32_t * const * const pivs, const len_t ncr, const uint32_t fc ) { hi_t i, j, k, l; len_t np = -1; const int64_t mod = (int64_t)fc; for (k = 0, i = *pc; i < ncr; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { np = i; } k++; continue; } const int64_t mul = mod - dr[i]; const len_t os = (ncr - i) % UNROLL; for (l = 0, j = i; l < os; ++l, ++j) { dr[j] += mul * pivs[i][l]; } for (; j < ncr; l += UNROLL, j += UNROLL) { dr[j] += mul * pivs[i][l]; dr[j+1] += mul * pivs[i][l+1]; dr[j+2] += mul * pivs[i][l+2]; dr[j+3] += mul * pivs[i][l+3]; } } if (k == 0) { *pc = -1; return NULL; } cf32_t *row = (cf32_t *)calloc((unsigned long)(ncr-np), sizeof(cf32_t)); for (i = np; i < ncr; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } row[i-np] = (cf32_t)dr[i]; } if (row[0] != 1) { row = normalize_dense_matrix_row_ff_32(row, ncr-np, fc); } *pc = np; return row; } static cf32_t *reduce_dense_row_by_dense_new_pivots_31_bit( int64_t *dr, len_t *pc, cf32_t * const * const pivs, const len_t ncr, const uint32_t fc ) { hi_t i, j, k, l; len_t np = -1; const int64_t mod = (int64_t)fc; const int64_t mod2 = (int64_t)fc * fc; for (k = 0, i = *pc; i < ncr; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { np = i; } k++; continue; } const int64_t mul = (int64_t)dr[i]; const len_t os = (ncr - i) % UNROLL; for (l = 0, j = i; l < os; ++l, ++j) { dr[j] -= mul * pivs[i][l]; dr[j] += (dr[j] >> 63) & mod2; } for (; j < ncr; l+=4, j += UNROLL) { dr[j] -= mul * pivs[i][l]; dr[j+1] -= mul * pivs[i][l+1]; dr[j+2] -= mul * pivs[i][l+2]; dr[j+3] -= mul * pivs[i][l+3]; dr[j] += (dr[j] >> 63) & mod2; dr[j+1] += (dr[j+1] >> 63) & mod2; dr[j+2] += (dr[j+2] >> 63) & mod2; dr[j+3] += (dr[j+3] >> 63) & mod2; } } if (k == 0) { *pc = -1; return NULL; } cf32_t *row = (cf32_t *)calloc((unsigned long)(ncr-np), sizeof(cf32_t)); for (i = np; i < ncr; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } row[i-np] = (cf32_t)dr[i]; } if (row[0] != 1) { row = normalize_dense_matrix_row_ff_32(row, ncr-np, fc); } *pc = np; return row; } static void probabilistic_sparse_reduced_echelon_form_ff_32( mat_t *mat, const bs_t * const bs, md_t *st ) { len_t i = 0, j, k, l, m; const len_t ncols = mat->nc; const len_t nrl = mat->nrl; const len_t ncr = mat->ncr; const len_t ncl = mat->ncl; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); j = nrl; for (i = 0; i < mat->nru; ++i) { mat->cf_32[j] = bs->cf_32[mat->rr[i][COEFFS]]; mat->rr[i][COEFFS] = j; ++j; } /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; const uint32_t fc = st->fc; /* Why do we generate the random linear combinations so strangely * compared to, e.g. la_ff_8.c or la_ff_16.c? * We can have fc > 2^31, so shifting the result of random multiplier * and coefficient may lead to elements of size > 2^63 which cannot * be represented by int64_t anymore. Thus we restrict the multiplier * via masking with mask to < 2^31. Then, after subtracting the * multiplied values we have to check if at some point the result gets * negative as int64_t, i.e. if drl[i] >> 63 is 1. If so, we add a * corresponding multiple of fc. Again, if fc > 2^31 we cannot just * add fc * fc, but we have to restrict to fc/2 * fc. * Note: We cannot apply this trick to the reduction itself, there we * cannot restrict the multiplier to be < 2^31, so we have to handle the * fc > 2^31 case differently. */ uint64_t tmp = (uint64_t)fc * fc; while (tmp > pow(2,63)) { tmp -= (uint64_t)(fc/2) * fc; } const int64_t mod2 = tmp; /* compute rows per block */ const len_t nb = (len_t)(floor(sqrt(nrl/3)))+1; const len_t rem = (nrl % nb == 0) ? 0 : 1; const len_t rpb = (nrl / nb) + rem; /* const int64_t mask = pow(2,(uint32_t)(ceil(log((double)st->max_uht_size)/log(2))))-1; */ const int64_t mask = pow(2,15)-1; int64_t *dr = (int64_t *)malloc( (unsigned long)(st->nthrds * ncols) * sizeof(int64_t)); int64_t *mul = (int64_t *)malloc( (unsigned long)(st->nthrds * rpb) * sizeof(int64_t)); /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ #pragma omp parallel for num_threads(st->nthrds) \ private(i, j, k, l, m) \ schedule(dynamic) for (i = 0; i < nb; ++i) { int64_t *drl = dr + (omp_get_thread_num() * ncols); int64_t *mull = mul + (omp_get_thread_num() * rpb); const int32_t nbl = (int32_t) (nrl > (i+1)*rpb ? (i+1)*rpb : nrl); const int32_t nrbl = (int32_t) (nbl - i*rpb); if (nrbl != 0) { hm_t *npiv = NULL; cf32_t *cfs; /* starting column, offset, coefficient array position in tmpcf */ hm_t sc, cfp; len_t bctr = 0; while (bctr < nrbl) { cfp = bctr + i*rpb; sc = 0; /* fill random value array */ for (j = 0; j < nrbl; ++j) { mull[j] = (int64_t)rand() & mask; } /* generate one dense row as random linear combination * of the rows of the block */ memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); for (k = 0, m = i*rpb; m < nbl; ++k, ++m) { npiv = upivs[m]; cfs = bs->cf_32[npiv[COEFFS]]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const hm_t * const ds = npiv + OFFSET; sc = sc < ds[0] ? sc : ds[0]; for (l = 0; l < os; ++l) { drl[ds[l]] -= mull[k] * cfs[l]; drl[ds[l]] += (drl[ds[l]] >> 63) & mod2; } for (; l < len; l += UNROLL) { drl[ds[l]] -= mull[k] * cfs[l]; drl[ds[l]] += (drl[ds[l]] >> 63) & mod2; drl[ds[l+1]] -= mull[k] * cfs[l+1]; drl[ds[l+1]] += (drl[ds[l+1]] >> 63) & mod2; drl[ds[l+2]] -= mull[k] * cfs[l+2]; drl[ds[l+2]] += (drl[ds[l+2]] >> 63) & mod2; drl[ds[l+3]] -= mull[k] * cfs[l+3]; drl[ds[l+3]] += (drl[ds[l+3]] >> 63) & mod2; } } k = 0; cfs = NULL; npiv = NULL; /* do the reduction */ do { free(cfs); cfs = NULL; free(npiv); npiv = NULL; npiv = reduce_dense_row_by_known_pivots_sparse_ff_32( drl, mat, bs, pivs, sc, cfp, 0, 0, 0, st); if (!npiv) { bctr = nrbl; break; } /* normalize coefficient array * NOTE: this has to be done here, otherwise the reduction may * lead to wrong results in a parallel computation since other * threads might directly use the new pivot once it is synced. */ if (mat->cf_32[npiv[COEFFS]][0] != 1) { normalize_sparse_matrix_row_ff_32( mat->cf_32[npiv[COEFFS]], npiv[PRELOOP], npiv[LENGTH], st->fc); } cfs = mat->cf_32[npiv[COEFFS]]; sc = npiv[OFFSET]; k = __sync_bool_compare_and_swap(&pivs[npiv[OFFSET]], NULL, npiv); } while (!k); bctr++; } for (j = i*rpb; j < nbl; ++j) { free(upivs[j]); upivs[j] = NULL; } } } free(mul); mul = NULL; /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { free(pivs[i]); pivs[i] = NULL; } len_t npivs = 0; /* number of new pivots */ dr = realloc(dr, (unsigned long)ncols * sizeof(int64_t)); mat->tr = realloc(mat->tr, (unsigned long)ncr * sizeof(hm_t *)); /* interreduce new pivots */ cf32_t *cfs; /* starting column, coefficient array position in tmpcf */ hm_t sc, cfp; for (i = 0; i < ncr; ++i) { k = ncols-1-i; if (pivs[k]) { memset(dr, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = mat->cf_32[pivs[k][COEFFS]]; cfp = pivs[k][COEFFS]; const len_t bi = pivs[k][BINDEX]; const len_t mh = pivs[k][MULT]; const len_t os = pivs[k][PRELOOP]; const len_t len = pivs[k][LENGTH]; const hm_t * const ds = pivs[k] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { dr[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] = (int64_t)cfs[j]; dr[ds[j+1]] = (int64_t)cfs[j+1]; dr[ds[j+2]] = (int64_t)cfs[j+2]; dr[ds[j+3]] = (int64_t)cfs[j+3]; } free(pivs[k]); free(cfs); pivs[k] = NULL; pivs[k] = mat->tr[npivs++] = reduce_dense_row_by_known_pivots_sparse_ff_32( dr, mat, bs, pivs, sc, cfp, mh, bi, 0, st); } } free(mat->rr); mat->rr = NULL; free(pivs); pivs = NULL; free(dr); dr = NULL; mat->tr = realloc(mat->tr, (unsigned long)npivs * sizeof(hi_t *)); st->np = mat->np = mat->nr = mat->sz = npivs; } static void sba_echelon_form_ff_32( smat_t *smat, crit_t *syz, md_t *st, const ht_t * const ht ) { len_t i, j; /* row index, might differ from i if we encounter zero reductions */ len_t ri; const len_t nc = smat->nc; const len_t nr = smat->cld; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)nc, sizeof(hm_t *)); int64_t *dr = (int64_t *)malloc( (unsigned long)nc * sizeof(int64_t)); /* TODO: At the moment I do not see how to make this parallel due to * reduction dependencies on the signatures. */ for (ri = 0, i = 0; i < nr; ++i) { hm_t *npiv = smat->cr[i]; cf32_t *cfs = smat->pc32[npiv[SM_CFS]]; const hm_t sm = npiv[SM_SMON]; const len_t si = npiv[SM_SIDX]; const len_t os = npiv[SM_PRE]; const len_t len = npiv[SM_LEN]; const hm_t * const ds = npiv + SM_OFFSET; memset(dr, 0, (unsigned long)nc * sizeof(int64_t)); for (j = 0; j < os; ++j) { dr[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] = (int64_t)cfs[j]; dr[ds[j+1]] = (int64_t)cfs[j+1]; dr[ds[j+2]] = (int64_t)cfs[j+2]; dr[ds[j+3]] = (int64_t)cfs[j+3]; } const len_t offset = npiv[SM_OFFSET]; free(npiv); npiv = NULL; smat->cr[i] = NULL; /* printf("reducing row %u || %u | %u -- ", i, sm, si); * for (int ii = 0; ii < ht->evl; ++ii) { * printf("%u ", ht->ev[sm][ii]); * } * printf("\n"); */ npiv = sba_reduce_dense_row_by_known_pivots_sparse_ff_32( dr, smat, pivs, offset, sm, si, ri, st); if (!npiv) { /* row s-reduced to zero, add syzygy and go on with next row */ add_syzygy_schreyer(syz, sm, si, ht); continue; } ri++; /* normalize coefficient array * NOTE: this has to be done here, otherwise the reduction may * lead to wrong results in a parallel computation since other * threads might directly use the new pivot once it is synced. */ if (smat->cc32[npiv[SM_CFS]][0] != 1) { normalize_sparse_matrix_row_ff_32( smat->cc32[npiv[SM_CFS]], npiv[SM_PRE], npiv[SM_LEN], st->fc); } pivs[npiv[SM_OFFSET]] = npiv; } /* free initial coefficients coming from previous degree matrix */ for (i = 0; i < smat->pld; ++i) { free(smat->pc32[i]); smat->pc32[i] = NULL; } /* get number of zero reductions and adjust number of * rows stored in matrix */ smat->nz = smat->cld - ri; smat->cld = ri; free(pivs); pivs = NULL; free(dr); dr = NULL; } static void exact_sparse_reduced_echelon_form_ff_32( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { len_t i = 0, j, k; hi_t sc = 0; /* starting column */ const len_t ncols = mat->nc; const len_t nrl = mat->nrl; const len_t ncr = mat->ncr; const len_t ncl = mat->ncl; const int32_t nthrds = st->in_final_reduction_step == 1 ? 1 : st->nthrds; len_t bad_prime = 0; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); if (st->in_final_reduction_step == 0) { memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); } else { for (i = 0; i < mat->nru; ++i) { pivs[mat->rr[i][OFFSET]] = mat->rr[i]; } } j = nrl; for (i = 0; i < mat->nru; ++i) { mat->cf_32[j] = bs->cf_32[mat->rr[i][COEFFS]]; mat->rr[i][COEFFS] = j; ++j; } /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; int64_t *dr = (int64_t *)malloc( (unsigned long)(nthrds * ncols) * sizeof(int64_t)); /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ #pragma omp parallel for num_threads(nthrds) \ private(i, j, k, sc) \ schedule(dynamic) for (i = 0; i < nrl; ++i) { if (bad_prime == 0) { int64_t *drl = dr + (omp_get_thread_num() * ncols); hm_t *npiv = upivs[i]; cf32_t *cfs = tbr->cf_32[npiv[COEFFS]]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const len_t bi = npiv[BINDEX]; const len_t mh = npiv[MULT]; const hm_t * const ds = npiv + OFFSET; k = 0; memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); for (j = 0; j < os; ++j) { drl[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { drl[ds[j]] = (int64_t)cfs[j]; drl[ds[j+1]] = (int64_t)cfs[j+1]; drl[ds[j+2]] = (int64_t)cfs[j+2]; drl[ds[j+3]] = (int64_t)cfs[j+3]; } cfs = NULL; do { /* If we do normal form computations the first monomial in the polynomial might not be a known pivot, thus setting it to npiv[OFFSET] can lead to wrong results. */ sc = st->nf == 0 ? npiv[OFFSET] : 0; free(npiv); free(cfs); npiv = mat->tr[i] = reduce_dense_row_by_known_pivots_sparse_ff_32( drl, mat, bs, pivs, sc, i, mh, bi, st->trace_level == LEARN_TRACER, st); if (st->nf > 0) { if (!npiv) { mat->tr[i] = NULL; break; } mat->tr[i] = npiv; cfs = mat->cf_32[npiv[COEFFS]]; break; } else { if (!npiv) { if (st->trace_level == APPLY_TRACER) { bad_prime = 1; } break; } /* normalize coefficient array * NOTE: this has to be done here, otherwise the reduction may * lead to wrong results in a parallel computation since other * threads might directly use the new pivot once it is synced. */ if (mat->cf_32[npiv[COEFFS]][0] != 1) { normalize_sparse_matrix_row_ff_32( mat->cf_32[npiv[COEFFS]], npiv[PRELOOP], npiv[LENGTH], st->fc); } k = __sync_bool_compare_and_swap(&pivs[npiv[OFFSET]], NULL, npiv); cfs = mat->cf_32[npiv[COEFFS]]; } } while (!k); } } if (bad_prime == 1) { for (i = 0; i < ncl+ncr; ++i) { free(pivs[i]); pivs[i] = NULL; } mat->np = 0; if (st->info_level > 0) { fprintf(stderr, "Zero reduction while applying tracer, bad prime.\n"); } return; } /* construct the trace */ if (st->trace_level == LEARN_TRACER && st->in_final_reduction_step == 0) { construct_trace(st->tr, mat); } /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { free(pivs[i]); pivs[i] = NULL; } len_t npivs = 0; /* number of new pivots */ if (st->nf == 0 && st->in_final_reduction_step == 0) { dr = realloc(dr, (unsigned long)ncols * sizeof(int64_t)); mat->tr = realloc(mat->tr, (unsigned long)ncr * sizeof(hm_t *)); /* interreduce new pivots */ cf32_t *cfs; hm_t cf_array_pos; for (i = 0; i < ncr; ++i) { k = ncols-1-i; if (pivs[k]) { memset(dr, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = mat->cf_32[pivs[k][COEFFS]]; cf_array_pos = pivs[k][COEFFS]; const len_t os = pivs[k][PRELOOP]; const len_t len = pivs[k][LENGTH]; const len_t bi = pivs[k][BINDEX]; const len_t mh = pivs[k][MULT]; const hm_t * const ds = pivs[k] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { dr[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] = (int64_t)cfs[j]; dr[ds[j+1]] = (int64_t)cfs[j+1]; dr[ds[j+2]] = (int64_t)cfs[j+2]; dr[ds[j+3]] = (int64_t)cfs[j+3]; } free(pivs[k]); free(cfs); pivs[k] = NULL; pivs[k] = mat->tr[npivs++] = reduce_dense_row_by_known_pivots_sparse_ff_32( dr, mat, bs, pivs, sc, cf_array_pos, mh, bi, 0, st); } } mat->tr = realloc(mat->tr, (unsigned long)npivs * sizeof(hi_t *)); st->np = mat->np = mat->nr = mat->sz = npivs; } else { st->np = mat->np = mat->nr = mat->sz = nrl; } free(pivs); pivs = NULL; free(dr); dr = NULL; } static void exact_sparse_reduced_echelon_form_sat_ff_32( bs_t *sat, mat_t *mat, bs_t *kernel, const bs_t * const bs, md_t *st ) { len_t i = 0, j, k; hi_t sc = 0; /* starting column */ double rt, ct; rt = realtime(); ct = cputime(); const len_t ncols = mat->nc; const len_t nrl = mat->nrl; const len_t ncl = mat->nru; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); /* saturation elements we have to reduce with the known pivots first */ hm_t **upivs = sat->hm; /* temporary storage for elements to be saturated */ /* bs_t *tmp = initialize_basis(sat->ld); */ /* temporary storage for corresponding multipliers * which then generate the kernel elements */ /* bs_t *mul = initialize_basis(sat->ld); */ int64_t *dr = (int64_t *)malloc( (unsigned long)(st->nthrds * ncols) * sizeof(int64_t)); /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ #pragma omp parallel for num_threads(st->nthrds) \ private(i, j, sc) \ schedule(dynamic) for (i = 0; i < sat->ld; ++i) { int64_t *drl = dr + (omp_get_thread_num() * ncols); hm_t *npiv = upivs[i]; len_t mult = npiv[MULT]; /* we only saturate w.r.t. one element at the moment */ len_t cf_idx = npiv[COEFFS]; cf32_t *cfs = sat->cf_32[cf_idx]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const hm_t * const ds = npiv + OFFSET; memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); for (j = 0; j < os; ++j) { drl[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { drl[ds[j]] = (int64_t)cfs[j]; drl[ds[j+1]] = (int64_t)cfs[j+1]; drl[ds[j+2]] = (int64_t)cfs[j+2]; drl[ds[j+3]] = (int64_t)cfs[j+3]; } sc = 0; while (drl[sc] == 0) { sc++; } free(npiv); upivs[i] = NULL; free(cfs); sat->cf_32[cf_idx] = NULL; /* npiv = reduce_dense_row_by_known_pivots_sparse_ff_32( * drl, mat, bs, pivs, sc, i, st); */ npiv = reduce_dense_row_by_known_pivots_sparse_up_to_ff_31_bit( drl, sat, bs, pivs, sc, cf_idx, i, ncl, ncols, st); if (!npiv) { #pragma omp critical { sat->hm[i] = NULL; kernel->hm[kernel->ld] = (hm_t *)malloc( (unsigned long)(OFFSET+1) * sizeof(hm_t)); kernel->cf_32[kernel->ld] = (cf32_t *)malloc( (unsigned long)1 * sizeof(cf32_t)); kernel->hm[kernel->ld][OFFSET] = mult; kernel->hm[kernel->ld][LENGTH] = 1; kernel->hm[kernel->ld][PRELOOP] = 1; kernel->hm[kernel->ld][COEFFS] = kernel->ld; kernel->cf_32[kernel->ld][0] = 1; kernel->ld++; } continue; } /* write non zero normal form to sat for reusage in a later * saturation step of f4sat */ npiv[MULT] = mult; sat->hm[i] = npiv; } mat->np = mat->nr = mat->sz = nrl; /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { free(pivs[i]); pivs[i] = NULL; } dr = realloc(dr, (unsigned long)ncols * sizeof(int64_t)); upivs = NULL; upivs = (hm_t **)calloc((unsigned long)sat->ld, sizeof(hm_t *)); len_t ctr = 0; if (st->info_level > 1) { printf(" normal form time"); } print_sat_nf_round_timings(stdout, st, rt, ct); /* compute kernel */ for (i = 0; i < sat->ld; ++i) { if (sat->hm[i] != NULL) { upivs[ctr++] = sat->hm[i]; } } sort_matrix_rows_mult_increasing(upivs, ctr); upivs = realloc(upivs, (unsigned long)ctr * sizeof(hm_t *)); /* first test if kernel is trivial */ /* if (is_kernel_trivial(sat, upivs, ncl, mat->ncr, st)) { * [> we do not need the old pivots anymore <] * for (i = 0; i < ncols; ++i) { * free(pivs[i]); * pivs[i] = NULL; * } * free(upivs); * upivs = NULL; * free(pivs); * pivs = NULL; * free(dr); * dr = NULL; * return; * } * * printf("not trivial! "); */ /* if kernel is not trivial really compute it */ /* dense row for multipliers */ hm_t **mulh = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); cf32_t **mulcf = (cf32_t **)calloc((unsigned long)ncols, sizeof(cf32_t *)); cf32_t **pivcf = (cf32_t **)calloc((unsigned long)ncols, sizeof(cf32_t *)); int64_t *drm = calloc((unsigned long)sat->ld, sizeof(int64_t)); /* now we do a ususal F4 reduction with updated pivs, but we have * to track the reduction steps when reducing each row from upivs */ for (i = 0; i < ctr; ++i) { int64_t *drl = dr; hm_t *npiv = upivs[i]; len_t tmp_pos = npiv[COEFFS]; cf32_t *cfs = sat->cf_32[tmp_pos]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const hm_t * const ds = npiv + OFFSET; k = 0; memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); memset(drm, 0, (unsigned long)sat->ld * sizeof(int64_t)); for (j = 0; j < os; ++j) { drl[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { drl[ds[j]] = (int64_t)cfs[j]; drl[ds[j+1]] = (int64_t)cfs[j+1]; drl[ds[j+2]] = (int64_t)cfs[j+2]; drl[ds[j+3]] = (int64_t)cfs[j+3]; } drm[upivs[i][MULT]] = 1; do { sc = npiv[OFFSET]; npiv = reduce_dense_row_by_known_pivots_sparse_sat_ff_31_bit( drl, drm, pivcf, mulh, mulcf, pivs, sc, tmp_pos, sat->ld, ncols, st, ncl); if (!npiv) { /* normalize new kernel element */ normalize_sparse_matrix_row_ff_32( mulcf[mulh[tmp_pos][COEFFS]], mulh[tmp_pos][PRELOOP], mulh[tmp_pos][LENGTH], st->fc); kernel->hm[kernel->ld] = mulh[tmp_pos]; kernel->cf_32[kernel->ld] = mulcf[mulh[tmp_pos][COEFFS]]; mulcf[mulh[tmp_pos][COEFFS]] = NULL; mulh[tmp_pos] = NULL; kernel->hm[kernel->ld][COEFFS] = kernel->ld; kernel->ld++; break; } /* normalize coefficient array * NOTE: this has to be done here, otherwise the reduction may * lead to wrong results in a parallel computation since other * threads might directly use the new pivot once it is synced. */ if (pivcf[npiv[COEFFS]][0] != 1) { /* adjust mul entry correspondingly */ adjust_multiplier_sparse_matrix_row_ff_32( mulcf[mulh[npiv[MULT]][COEFFS]], pivcf[npiv[COEFFS]], mulh[npiv[MULT]][PRELOOP], mulh[npiv[MULT]][LENGTH], st->fc); /* for (int kk = 0; kk < mulh[npiv[MULT]][LENGTH]; ++kk) { * printf("%u ", mulcf[mulh[npiv[MULT]][COEFFS]][kk]); * } * printf("\n"); */ normalize_sparse_matrix_row_ff_32( pivcf[npiv[COEFFS]], npiv[PRELOOP], npiv[LENGTH], st->fc); } k = __sync_bool_compare_and_swap(&pivs[npiv[OFFSET]], NULL, npiv); } while (!k); } /* we do not need the old pivots anymore */ for (i = 0; i < ncols; ++i) { free(pivs[i]); pivs[i] = NULL; } for (i = 0; i < ncols; ++i) { free(mulcf[i]); mulcf[i] = NULL; free(pivcf[i]); pivcf[i] = NULL; free(mulh[i]); mulh[i] = NULL; } free(pivcf); pivcf = NULL; free(mulcf); mulcf = NULL; free(mulh); mulh = NULL; free(upivs); upivs = NULL; free(pivs); pivs = NULL; free(dr); dr = NULL; free(drm); drm = NULL; } static void exact_trace_sparse_reduced_echelon_form_ff_32( trace_t *trace, mat_t *mat, const bs_t * const bs, md_t *st ) { len_t i = 0, j, k; hi_t sc = 0; /* starting column */ const len_t ncols = mat->nc; const len_t nrl = mat->nrl; const len_t ncr = mat->ncr; const len_t ncl = mat->ncl; const int32_t nthrds = st->in_final_reduction_step == 1 ? 1 : st->nthrds; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; int64_t *dr = (int64_t *)malloc( (unsigned long)(nthrds * ncols) * sizeof(int64_t)); /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ #pragma omp parallel for num_threads(nthrds) \ private(i, j, k, sc) \ schedule(dynamic) for (i = 0; i < nrl; ++i) { int64_t *drl = dr + (omp_get_thread_num() * ncols); hm_t *npiv = upivs[i]; rba_t *rba = mat->rba[i]; cf32_t *cfs = bs->cf_32[npiv[COEFFS]]; const len_t bi = npiv[BINDEX]; const len_t mh = npiv[MULT]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const hm_t * const ds = npiv + OFFSET; k = 0; memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); for (j = 0; j < os; ++j) { drl[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { drl[ds[j]] = (int64_t)cfs[j]; drl[ds[j+1]] = (int64_t)cfs[j+1]; drl[ds[j+2]] = (int64_t)cfs[j+2]; drl[ds[j+3]] = (int64_t)cfs[j+3]; } cfs = NULL; do { sc = npiv[OFFSET]; free(npiv); free(cfs); npiv = mat->tr[i] = trace_reduce_dense_row_by_known_pivots_sparse_ff_32( rba, drl, mat, bs, pivs, sc, i, mh, bi, st); if (!npiv) { break; } /* normalize coefficient array * NOTE: this has to be done here, otherwise the reduction may * lead to wrong results in a parallel computation since other * threads might directly use the new pivot once it is synced. */ if (mat->cf_32[npiv[COEFFS]][0] != 1) { normalize_sparse_matrix_row_ff_32( mat->cf_32[npiv[COEFFS]], npiv[PRELOOP], npiv[LENGTH], st->fc); st->trace_nr_mult += npiv[LENGTH] / 1000.0; } k = __sync_bool_compare_and_swap(&pivs[npiv[OFFSET]], NULL, npiv); cfs = mat->cf_32[npiv[COEFFS]]; } while (!k); } /* construct the trace */ construct_trace(trace, mat); /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { free(pivs[i]); pivs[i] = NULL; } len_t npivs = 0; /* number of new pivots */ dr = realloc(dr, (unsigned long)ncols * sizeof(int64_t)); mat->tr = realloc(mat->tr, (unsigned long)ncr * sizeof(hm_t *)); /* interreduce new pivots */ cf32_t *cfs; hm_t cf_array_pos; for (i = 0; i < ncr; ++i) { k = ncols-1-i; if (pivs[k]) { memset(dr, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = mat->cf_32[pivs[k][COEFFS]]; cf_array_pos = pivs[k][COEFFS]; const len_t os = pivs[k][PRELOOP]; const len_t len = pivs[k][LENGTH]; const len_t bi = pivs[k][BINDEX]; const len_t mh = pivs[k][MULT]; const hm_t * const ds = pivs[k] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { dr[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] = (int64_t)cfs[j]; dr[ds[j+1]] = (int64_t)cfs[j+1]; dr[ds[j+2]] = (int64_t)cfs[j+2]; dr[ds[j+3]] = (int64_t)cfs[j+3]; } free(pivs[k]); free(cfs); pivs[k] = NULL; pivs[k] = mat->tr[npivs++] = reduce_dense_row_by_known_pivots_sparse_ff_32( dr, mat, bs, pivs, sc, cf_array_pos, mh, bi, 0, st); } } free(pivs); pivs = NULL; free(dr); dr = NULL; mat->tr = realloc(mat->tr, (unsigned long)npivs * sizeof(hi_t *)); st->np = mat->np = mat->nr = mat->sz = npivs; } static int exact_application_sparse_reduced_echelon_form_ff_32( mat_t *mat, const bs_t * const bs, md_t *st ) { len_t i = 0, j, k; hi_t sc = 0; /* starting column */ const len_t ncols = mat->nc; const len_t nrl = mat->nrl; const len_t ncr = mat->ncr; const len_t ncl = mat->ncl; const int32_t nthrds = st->in_final_reduction_step == 1 ? 1 : st->nthrds; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; int64_t *dr = (int64_t *)malloc( (unsigned long)(nthrds * ncols) * sizeof(int64_t)); /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ int flag = 1; #pragma omp parallel for num_threads(nthrds) \ private(i, j, k, sc) \ schedule(dynamic) for (i = 0; i < nrl; ++i) { if (flag == 1) { int64_t *drl = dr + (omp_get_thread_num() * ncols); hm_t *npiv = upivs[i]; cf32_t *cfs = bs->cf_32[npiv[COEFFS]]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const len_t bi = npiv[BINDEX]; const len_t mh = npiv[MULT]; const hm_t * const ds = npiv + OFFSET; k = 0; memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); for (j = 0; j < os; ++j) { drl[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { drl[ds[j]] = (int64_t)cfs[j]; drl[ds[j+1]] = (int64_t)cfs[j+1]; drl[ds[j+2]] = (int64_t)cfs[j+2]; drl[ds[j+3]] = (int64_t)cfs[j+3]; } cfs = NULL; do { sc = npiv[OFFSET]; free(npiv); free(cfs); npiv = mat->tr[i] = reduce_dense_row_by_known_pivots_sparse_ff_32( drl, mat, bs, pivs, sc, i, mh, bi, 0, st); if (!npiv) { fprintf(stderr, "Unlucky prime detected, row reduced to zero."); flag = 0; break; } /* normalize coefficient array * NOTE: this has to be done here, otherwise the reduction may * lead to wrong results in a parallel computation since other * threads might directly use the new pivot once it is synced. */ if (mat->cf_32[npiv[COEFFS]][0] != 1) { normalize_sparse_matrix_row_ff_32( mat->cf_32[npiv[COEFFS]], npiv[PRELOOP], npiv[LENGTH], st->fc); st->application_nr_mult += npiv[LENGTH] / 1000.0; } k = __sync_bool_compare_and_swap(&pivs[npiv[OFFSET]], NULL, npiv); cfs = mat->cf_32[npiv[COEFFS]]; } while (!k); } } /* unlucky prime found */ if (flag == 0) { return 1; } /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { free(pivs[i]); pivs[i] = NULL; } len_t npivs = 0; /* number of new pivots */ dr = realloc(dr, (unsigned long)ncols * sizeof(int64_t)); mat->tr = realloc(mat->tr, (unsigned long)ncr * sizeof(hm_t *)); /* interreduce new pivots */ cf32_t *cfs; hm_t cf_array_pos; for (i = 0; i < ncr; ++i) { k = ncols-1-i; if (pivs[k]) { memset(dr, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = mat->cf_32[pivs[k][COEFFS]]; cf_array_pos = pivs[k][COEFFS]; const len_t os = pivs[k][PRELOOP]; const len_t len = pivs[k][LENGTH]; const len_t bi = pivs[k][BINDEX]; const len_t mh = pivs[k][MULT]; const hm_t * const ds = pivs[k] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { dr[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] = (int64_t)cfs[j]; dr[ds[j+1]] = (int64_t)cfs[j+1]; dr[ds[j+2]] = (int64_t)cfs[j+2]; dr[ds[j+3]] = (int64_t)cfs[j+3]; } free(pivs[k]); free(cfs); pivs[k] = NULL; pivs[k] = mat->tr[npivs++] = reduce_dense_row_by_known_pivots_sparse_ff_32( dr, mat, bs, pivs, sc, cf_array_pos, mh, bi, 0, st); } } free(pivs); pivs = NULL; free(dr); dr = NULL; mat->tr = realloc(mat->tr, (unsigned long)npivs * sizeof(hi_t *)); st->np = mat->np = mat->nr = mat->sz = npivs; return 0; } static cf32_t **sparse_AB_CD_linear_algebra_ff_32( mat_t *mat, const bs_t * bs, md_t *st ) { len_t i = 0, j; hi_t sc = 0; /* starting column */ const len_t ncols = mat->nc; const len_t nrl = mat->nrl; const len_t ncl = mat->ncl; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; /* dense rows representing updated D part; * after reducing CD part with AB */ cf32_t **drs = (cf32_t **)calloc((unsigned long)nrl, sizeof(cf32_t *)); int64_t *dr = (int64_t *)malloc( (unsigned long)(st->nthrds * ncols) * sizeof(int64_t)); /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ #pragma omp parallel for num_threads(st->nthrds) \ private(i, j, sc) \ schedule(dynamic) for (i = 0; i < nrl; ++i) { cf32_t *cfs = NULL; int64_t *drl = dr + (omp_get_thread_num() * ncols); hm_t *npiv = upivs[i]; /* do the reduction */ memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = bs->cf_32[npiv[COEFFS]]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const hm_t * const ds = npiv + OFFSET; for (j = 0; j < os; ++j) { drl[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { drl[ds[j]] = (int64_t)cfs[j]; drl[ds[j+1]] = (int64_t)cfs[j+1]; drl[ds[j+2]] = (int64_t)cfs[j+2]; drl[ds[j+3]] = (int64_t)cfs[j+3]; } sc = ds[0]; free(npiv); drs[i] = reduce_dense_row_by_old_pivots_ff_32( drl, mat, bs, pivs, sc, st->fc); } free(dr); dr = NULL; /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { free(pivs[i]); pivs[i] = NULL; } free(pivs); pivs = NULL; /* remove NULL dense rows */ len_t npivs = 0; /* number of new pivots */ for (i = 0; i < nrl; ++i) { if (drs[i] != NULL) { drs[npivs++] = drs[i]; } } if (npivs == 0) { free(drs); drs = NULL; } st->np = mat->np = npivs; return drs; } static cf32_t **interreduce_dense_matrix_ff_32( cf32_t **dm, const len_t ncr, const uint32_t fc ) { len_t i, j, k, l; int64_t *dr = malloc((unsigned long)ncr * sizeof(int64_t)); for (i = 0; i < ncr; ++i) { k = ncr-1-i; if (dm[k]) { memset(dr, 0, (unsigned long)ncr * sizeof(int64_t)); const len_t npc = ncr - k; const len_t os = npc % UNROLL; for (j = k, l = 0; l < os; ++j, ++l) { dr[j] = (int64_t)dm[k][l]; } for (; l < npc; j += UNROLL, l += UNROLL) { dr[j] = (int64_t)dm[k][l]; dr[j+1] = (int64_t)dm[k][l+1]; dr[j+2] = (int64_t)dm[k][l+2]; dr[j+3] = (int64_t)dm[k][l+3]; } free(dm[k]); dm[k] = NULL; /* start with previous pivot the reduction process, so keep the * pivot element as it is */ dm[k] = reduce_dense_row_by_dense_new_pivots_ff_32( dr, &k, dm, ncr, fc); } } free(dr); return dm; } static cf32_t **exact_dense_linear_algebra_ff_32( cf32_t **dm, mat_t *mat, md_t *st ) { len_t i, j, k, l, npivs; const len_t nrows = mat->np; /* we need the pivots until now here */ const len_t ncr = mat->ncr; /* rows already representing new pivots */ cf32_t **nps = (cf32_t **)calloc((unsigned long)ncr, sizeof(cf32_t *)); /* rows to be further reduced */ cf32_t **tbr = (cf32_t **)calloc((unsigned long)nrows, sizeof(cf32_t *)); int64_t *dr = (int64_t *)malloc( (unsigned long)(st->nthrds * ncr) * sizeof(int64_t)); /* separate rows already representing new pivots and rows to * be further reduced by these new pivots */ j = 0; npivs = 0; for (i = 0; i < nrows; ++i) { if (dm[i] != NULL) { k = 0; while (dm[i][k] == 0) { ++k; } if (nps[k] == NULL) { /* we have a pivot, cut the dense row down to start * at the first nonzero entry */ memmove(dm[i], dm[i]+k, (unsigned long)(ncr-k) * sizeof(cf32_t)); dm[i] = realloc(dm[i], (unsigned long)(ncr-k) * sizeof(cf32_t)); nps[k] = dm[i]; if (nps[k][0] != 1) { nps[k] = normalize_dense_matrix_row_ff_32(nps[k], ncr-k, st->fc); } } else { tbr[j++] = dm[i]; } } } free(dm); dm = NULL; const len_t ntr = j; tbr = realloc(tbr, (unsigned long)ntr * sizeof(cf32_t *)); /* offset modulo 4 for loop unrolling, +1 due to storing the first * nonzero entry at the first position */ /* reduction process to get all possible pivots, no interreduction here */ #pragma omp parallel for num_threads(st->nthrds) \ private(i, j, k, l) shared(nps, tbr) \ schedule(dynamic) for (i = 0; i < ntr; ++i) { int64_t *drl = dr + (omp_get_thread_num() * ncr); memset(drl, 0, (unsigned long)ncr * sizeof(int64_t)); hm_t npc = 0; hm_t os = 0; cf32_t *npiv = tbr[i]; os = (ncr-npc) % UNROLL; for (l = 0, j = npc; l < os; ++l, ++j) { drl[j] = (int64_t)npiv[l]; } for (; j < ncr; l += UNROLL, j += UNROLL) { drl[j] = (int64_t)npiv[l]; drl[j+1] = (int64_t)npiv[l+1]; drl[j+2] = (int64_t)npiv[l+2]; drl[j+3] = (int64_t)npiv[l+3]; } do { free(npiv); npiv = NULL; npiv = reduce_dense_row_by_dense_new_pivots_ff_32( drl, &npc, nps, mat->ncr, st->fc); if (npc == -1) { break; } k = __sync_bool_compare_and_swap(&nps[npc], NULL, npiv); /* some other thread has already added a pivot so we have to * recall the dense reduction process */ } while (!k); } /* count number of pivots */ const len_t os = ncr % UNROLL; for (i = 0; i < os; ++i) { if (nps[i] != NULL) { npivs++; } } for (; i < ncr; i += UNROLL) { if (nps[i] != NULL) { npivs++; } if (nps[i+1] != NULL) { npivs++; } if (nps[i+2] != NULL) { npivs++; } if (nps[i+3] != NULL) { npivs++; } } st->np = mat->np = npivs; free(tbr); free(dr); return nps; } static cf32_t **probabilistic_dense_linear_algebra_ff_32( cf32_t **dm, mat_t *mat, md_t *st ) { len_t i, j, k, l, m, npivs; const uint32_t fc = st->fc; const len_t nrows = mat->np; /* we need the pivots until now here */ const len_t ncols = mat->nc; const len_t ncr = mat->ncr; /* rows already representing new pivots */ cf32_t **nps = (cf32_t **)calloc((unsigned long)ncr, sizeof(cf32_t *)); /* rows to be further reduced */ cf32_t **tbr = (cf32_t **)calloc((unsigned long)nrows, sizeof(cf32_t *)); /* separate rows already representing new pivots and rows to * be further reduced by these new pivots */ j = 0; npivs = 0; for (i = 0; i < nrows; ++i) { if (dm[i] != NULL) { k = 0; while (dm[i][k] == 0) { ++k; } if (nps[k] == NULL) { /* we have a pivot, cut the dense row down to start * at the first nonzero entry */ memmove(dm[i], dm[i]+k, (unsigned long)(ncr-k) * sizeof(cf32_t)); dm[i] = realloc(dm[i], (unsigned long)(ncr-k) * sizeof(cf32_t)); nps[k] = dm[i]; if (nps[k][0] != 1) { nps[k] = normalize_dense_matrix_row_ff_32(nps[k], ncr-k, st->fc); } } else { tbr[j++] = dm[i]; } } } free(dm); dm = NULL; const len_t ntr = j; tbr = realloc(tbr, (unsigned long)ntr * sizeof(cf32_t *)); /* Why do we generate the random linear combinations so strangely * compared to, e.g. la_ff_8.c or la_ff_16.c? * We can have fc > 2^31, so shifting the result of random multiplier * and coefficient may lead to elements of size > 2^63 which cannot * be represented by int64_t anymore. Thus we restrict the multiplier * via masking with mask to < 2^31. Then, after subtracting the * multiplied values we have to check if at some point the result gets * negative as int64_t, i.e. if drl[i] >> 63 is 1. If so, we add a * corresponding multiple of fc. Again, if fc > 2^31 we cannot just * add fc * fc, but we have to restrict to fc/2 * fc. * Note: We cannot apply this trick to the reduction itself, there we * cannot restrict the multiplier to be < 2^31, so we have to handle the * fc > 2^31 case differently. */ uint64_t tmp = (uint64_t)fc * fc; while (tmp > pow(2,63)) { tmp -= (uint64_t)(fc/2) * fc; } const int64_t mod2 = tmp; /* compute rows per block */ const len_t nb = (len_t)(floor(sqrt(ntr/3)))+1; const len_t rem = (ntr % nb == 0) ? 0 : 1; const len_t rpb = (ntr / nb) + rem; /* const int64_t mask = pow(2,(uint32_t)(ceil(log((double)st->max_uht_size)/log(2))))-1; */ const int64_t mask = pow(2,15)-1; int64_t *dr = (int64_t *)malloc( (unsigned long)(st->nthrds * ncols) * sizeof(int64_t)); int64_t *mul = (int64_t *)malloc( (unsigned long)(st->nthrds * rpb) * sizeof(int64_t)); /* reduction process to get all possible pivots, no interreduction here */ #pragma omp parallel for num_threads(st->nthrds) \ private(i, j, k, l) shared(nps, tbr) \ schedule(dynamic) for (i = 0; i < ntr; ++i) { int64_t *drl = dr + (omp_get_thread_num() * ncr); int64_t *mull = mul + (omp_get_thread_num() * rpb); const int32_t nbl = (int32_t) (ntr > (i+1)*rpb ? (i+1)*rpb : ntr); const int32_t nrbl = (int32_t) (nbl - i*rpb); if (nrbl > 0) { hm_t npc; hm_t os; cf32_t *tmp; len_t bctr = 0; while (bctr < nrbl) { npc = 0; os = ncr % UNROLL; /* fill random value array */ for (j = 0; j < nrbl; ++j) { mull[j] = (int64_t)rand() & mask; } /* generate one dense row as random linear combination * of the rows of the block */ memset(drl, 0, (unsigned long)ncr * sizeof(int64_t)); for (k = 0, m = i*rpb; m < nbl; ++k, ++m) { tmp = tbr[m]; for (l = 0, j = npc; l < os; ++l, ++j) { drl[j] -= mull[k] * tmp[l]; drl[j] += (drl[j] >> 63) & mod2; } for (; j < ncr; l += UNROLL, j += UNROLL) { drl[j] -= mull[k] * tmp[l]; drl[j] += (drl[j] >> 63) & mod2; drl[j+1] -= mull[k] * tmp[l+1]; drl[j+1] += (drl[j+1] >> 63) & mod2; drl[j+2] -= mull[k] * tmp[l+2]; drl[j+2] += (drl[j+2] >> 63) & mod2; drl[j+3] -= mull[k] * tmp[l+3]; drl[j+3] += (drl[j+3] >> 63) & mod2; } } k = 0; npc = 0; /* do the reduction */ tmp = NULL; do { free(tmp); tmp = reduce_dense_row_by_dense_new_pivots_ff_32( drl, &npc, nps, mat->ncr, st->fc); if (npc == -1) { bctr = nrbl; break; } k = __sync_bool_compare_and_swap(&nps[npc], NULL, tmp); /* some other thread has already added a pivot so we have to * recall the dense reduction process */ } while (!k); bctr++; } for (j = i*rpb; j < nbl; ++j) { free(tbr[j]); tbr[j] = NULL; } } } /* count number of pivots */ const len_t os = ncr % UNROLL; for (i = 0; i < os; ++i) { if (nps[i] != NULL) { npivs++; } } for (; i < ncr; i += UNROLL) { if (nps[i] != NULL) { npivs++; } if (nps[i+1] != NULL) { npivs++; } if (nps[i+2] != NULL) { npivs++; } if (nps[i+3] != NULL) { npivs++; } } st->np = mat->np = npivs; free(mul); free(tbr); free(dr); return nps; } static cf32_t **probabilistic_sparse_dense_echelon_form_ff_32( mat_t *mat, const bs_t * const bs, md_t *st ) { len_t i = 0, j, k, l, m, npivs; const len_t nru = mat->nru; const len_t nrl = mat->nrl; const len_t ncr = mat->ncr; const len_t ncols = mat->nc; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; /* rows already representing new pivots */ cf32_t **nps = (cf32_t **)calloc((unsigned long)ncr, sizeof(cf32_t *)); const uint32_t fc = st->fc; const int64_t mod2 = (int64_t)fc * fc; /* compute rows per block */ const len_t nb = (len_t)(floor(sqrt(nrl/3)))+1; const len_t rem = (nrl % nb == 0) ? 0 : 1; const len_t rpb = (nrl / nb) + rem; int64_t *dr = (int64_t *)malloc( (unsigned long)(st->nthrds * ncols) * sizeof(int64_t)); int64_t *mul = (int64_t *)malloc( (unsigned long)(st->nthrds * rpb) * sizeof(int64_t)); /* reduction process to get all possible pivots, no interreduction here */ #pragma omp parallel for num_threads(st->nthrds) \ private(i, j, k, l, m) shared(nps) \ schedule(dynamic) for (i = 0; i < nb; ++i) { int64_t *drl = dr + (omp_get_thread_num() * ncols); int64_t *mull = mul + (omp_get_thread_num() * rpb); const int32_t nbl = (int32_t) (nrl > (i+1)*rpb ? (i+1)*rpb : nrl); const int32_t nrbl = (int32_t) (nbl - i*rpb); if (nrbl > 0) { hm_t *npiv; cf32_t *tmp; hm_t npc; len_t bctr = 0; while (bctr < nrbl) { npc = 0; /* fill random value array */ for (j = 0; j < nrbl; ++j) { mull[j] = (int64_t)rand() % fc; } /* generate one dense row as random linear combination * of the rows of the block */ memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); for (k = 0, m = i*rpb; m < nbl; ++k, ++m) { npiv = upivs[m]; tmp = bs->cf_32[npiv[COEFFS]]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const hm_t * const ds = npiv + OFFSET; for (l = 0; l < os; ++l) { drl[ds[l]] -= mull[k] * tmp[l]; drl[ds[l]] += (drl[ds[l]] >> 63) & mod2; } for (; l < len; l += UNROLL) { drl[ds[l]] -= mull[k] * tmp[l]; drl[ds[l]] += (drl[ds[l]] >> 63) & mod2; drl[ds[l+1]] -= mull[k] * tmp[l+1]; drl[ds[l+1]] += (drl[ds[l+1]] >> 63) & mod2; drl[ds[l+2]] -= mull[k] * tmp[l+2]; drl[ds[l+2]] += (drl[ds[l+2]] >> 63) & mod2; drl[ds[l+3]] -= mull[k] * tmp[l+3]; drl[ds[l+3]] += (drl[ds[l+3]] >> 63) & mod2; } } k = 0; npc = 0; /* do the reduction */ tmp = NULL; do { free(tmp); tmp = reduce_dense_row_by_all_pivots_ff_32( drl, mat, bs, &npc, pivs, nps, st->fc); if (npc == -1) { bctr = nrbl; break; } k = __sync_bool_compare_and_swap(&nps[npc], NULL, tmp); /* some other thread has already added a pivot so we have to * recall the dense reduction process */ } while (!k); bctr++; } for (j = i*rpb; j < nbl; ++j) { free(upivs[j]); upivs[j] = NULL; } } } npivs = 0; /* count number of pivots */ const len_t os = ncr % UNROLL; for (i = 0; i < os; ++i) { if (nps[i] != NULL) { npivs++; } } for (; i < ncr; i += UNROLL) { if (nps[i] != NULL) { npivs++; } if (nps[i+1] != NULL) { npivs++; } if (nps[i+2] != NULL) { npivs++; } if (nps[i+3] != NULL) { npivs++; } } st->np = mat->np = npivs; for (i = 0; i < nru; ++i) { free(pivs[i]); } free(pivs); pivs = NULL; free(mul); mul = NULL; free(dr); dr = NULL; return nps; } static void convert_to_sparse_matrix_rows_ff_32( mat_t *mat, cf32_t * const * const dm ) { if (mat->np == 0) { return; } len_t i, j, k, l, m; cf32_t *cfs; hm_t *dts, *dss; const len_t ncr = mat->ncr; const len_t ncl = mat->ncl; mat->tr = realloc(mat->tr, (unsigned long)mat->np * sizeof(hm_t *)); mat->cf_32 = realloc(mat->cf_32, (unsigned long)mat->np * sizeof(cf32_t *)); l = 0; for (i = 0; i < ncr; ++i) { m = ncr-1-i; if (dm[m] != NULL) { cfs = malloc((unsigned long)(ncr-m) * sizeof(cf32_t)); dts = malloc((unsigned long)(ncr-m+OFFSET) * sizeof(hm_t)); const hm_t len = ncr-m; const hm_t os = len % UNROLL; const hm_t shift = ncl+m; dss = dts + OFFSET; for (k = 0, j = 0; j < os; ++j) { if (dm[m][j] != 0) { cfs[k] = dm[m][j]; dss[k++] = j+shift; } } for (; j < len; j += UNROLL) { if (dm[m][j] != 0) { cfs[k] = dm[m][j]; dss[k++] = j+shift; } if (dm[m][j+1] != 0) { cfs[k] = dm[m][j+1]; dss[k++] = j+1+shift; } if (dm[m][j+2] != 0) { cfs[k] = dm[m][j+2]; dss[k++] = j+2+shift; } if (dm[m][j+3] != 0) { cfs[k] = dm[m][j+3]; dss[k++] = j+3+shift; } } /* store meta data in first entries */ dts[COEFFS] = l; /* position of coefficient array in tmpcf */ dts[PRELOOP] = k % UNROLL; dts[LENGTH] = k; /* adjust memory usage */ dts = realloc(dts, (unsigned long)(k+OFFSET) * sizeof(hm_t)); cfs = realloc(cfs, (unsigned long)k * sizeof(cf32_t)); /* link to basis */ mat->tr[l] = dts; mat->cf_32[l] = cfs; l++; } } } /* NOTE: this note is about the different linear algebra implementations: * exact and probabilistic linear algebra differ only in the last, * dense reduction step: the reduction of CD via AB is sparse and * the same for both. this generates a dense D' part which is then * either reduced via exact linear algebra or via probabilistic * linear algebra */ static void probabilistic_sparse_linear_algebra_ff_32( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* allocate temporary storage space for sparse * coefficients of all pivot rows */ mat->cf_32 = realloc(mat->cf_32, (unsigned long)mat->nr * sizeof(cf32_t *)); probabilistic_sparse_reduced_echelon_form_ff_32(mat, bs, st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static void sba_linear_algebra_ff_32( smat_t *smat, crit_t *syz, md_t *st, const ht_t * const ht ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); smat->cc32 = realloc(smat->cc32, (unsigned long)smat->cld * sizeof(cf32_t *)); sba_echelon_form_ff_32(smat, syz, st, ht); /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += smat->nz; } /* In f4: tbr == bs in nf: tbr are the polynomials to be reduced w.r.t. bs */ static void exact_sparse_linear_algebra_ff_32( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* allocate temporary storage space for sparse * coefficients of all pivot rows */ mat->cf_32 = realloc(mat->cf_32, (unsigned long)mat->nr * sizeof(cf32_t *)); exact_sparse_reduced_echelon_form_ff_32(mat, tbr, bs, st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static void copy_kernel_to_matrix( mat_t *mat, bs_t *kernel, const len_t nc ) { len_t i; sort_matrix_rows_increasing(kernel->hm, kernel->ld); mat->tr = (hm_t **)malloc((unsigned long)kernel->ld * sizeof(hm_t *)); mat->nr = kernel->ld; mat->nc = nc; mat->nru = 0; mat->nrl = kernel->ld; mat->ncl = 0; mat->ncr = mat->nc; for (i = 0; i < kernel->ld; ++i) { mat->tr[i] = kernel->hm[i]; } } static void compute_kernel_sat_ff_32( bs_t *sat, mat_t *mat, bs_t *kernel, const bs_t * const bs, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); check_enlarge_basis(kernel, sat->ld, st); exact_sparse_reduced_echelon_form_sat_ff_32( sat, mat, kernel, bs, st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; } static int exact_application_sparse_linear_algebra_ff_32( mat_t *mat, const bs_t * const bs, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); int ret; /* allocate temporary storage space for sparse * coefficients of all pivot rows */ mat->cf_32 = realloc(mat->cf_32, (unsigned long)mat->nr * sizeof(cf32_t *)); ret = exact_application_sparse_reduced_echelon_form_ff_32(mat, bs, st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } return ret; } static void exact_trace_sparse_linear_algebra_ff_32( trace_t *trace, mat_t *mat, const bs_t * const bs, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* allocate temporary storage space for sparse * coefficients of all pivot rows */ mat->cf_32 = realloc(mat->cf_32, (unsigned long)mat->nr * sizeof(cf32_t *)); exact_trace_sparse_reduced_echelon_form_ff_32(trace, mat, bs, st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static void exact_sparse_dense_linear_algebra_ff_32( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { len_t i; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); const len_t ncr = mat->ncr; /* generate updated dense D part via reduction of CD with AB */ cf32_t **dm; dm = sparse_AB_CD_linear_algebra_ff_32(mat, bs, st); if (mat->np > 0) { dm = exact_dense_linear_algebra_ff_32(dm, mat, st); dm = interreduce_dense_matrix_ff_32(dm, ncr, st->fc); } /* convert dense matrix back to sparse matrix representation, * use tmpcf for storing the coefficient arrays */ convert_to_sparse_matrix_rows_ff_32(mat, dm); /* free dm */ if (dm) { for (i = 0; i < ncr; ++i) { free(dm[i]); } free(dm); dm = NULL; } /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static void probabilistic_sparse_dense_linear_algebra_ff_32_2( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { len_t i; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); const len_t ncr = mat->ncr; /* generate updated dense D part via reduction of CD with AB */ cf32_t **dm; dm = sparse_AB_CD_linear_algebra_ff_32(mat, bs, st); if (mat->np > 0) { dm = probabilistic_dense_linear_algebra_ff_32(dm, mat, st); dm = interreduce_dense_matrix_ff_32(dm, mat->ncr, st->fc); } /* convert dense matrix back to sparse matrix representation, * use tmpcf for storing the coefficient arrays */ convert_to_sparse_matrix_rows_ff_32(mat, dm); /* free dm */ if (dm) { for (i = 0; i < ncr; ++i) { free(dm[i]); } free(dm); dm = NULL; } /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static void probabilistic_sparse_dense_linear_algebra_ff_32( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { len_t i; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); const len_t ncr = mat->ncr; /* generate updated dense D part via reduction of CD with AB */ cf32_t **dm = NULL; mat->np = 0; dm = probabilistic_sparse_dense_echelon_form_ff_32(mat, bs, st); dm = interreduce_dense_matrix_ff_32(dm, mat->ncr, st->fc); /* convert dense matrix back to sparse matrix representation, * use tmpcf for storing the coefficient arrays */ convert_to_sparse_matrix_rows_ff_32(mat, dm); /* free dm */ if (dm) { for (i = 0; i < ncr; ++i) { free(dm[i]); } free(dm); dm = NULL; } /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static void interreduce_matrix_rows_ff_32( mat_t *mat, bs_t *bs, md_t *st, const int free_basis ) { len_t i, j, k, l; const len_t nrows = mat->nr; const len_t ncols = mat->nc; /* adjust displaying timings for statistic printout */ if (st->info_level > 1) { printf(" "); } mat->tr = realloc(mat->tr, (unsigned long)ncols * sizeof(hm_t *)); mat->cf_32 = realloc(mat->cf_32, (unsigned long)ncols * sizeof(cf32_t *)); memset(mat->cf_32, 0, (unsigned long)ncols * sizeof(cf32_t *)); hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); /* copy coefficient arrays from basis in matrix, maybe * several rows need the same coefficient arrays, but we * cannot share them here. */ for (i = 0; i < nrows; ++i) { pivs[mat->rr[i][OFFSET]] = mat->rr[i]; } int64_t *dr = (int64_t *)malloc((unsigned long)ncols * sizeof(int64_t)); /* interreduce new pivots */ cf32_t *cfs; /* starting column, coefficient array position in tmpcf */ hm_t sc; k = nrows - 1; for (i = 0; i < ncols; ++i) { l = ncols-1-i; if (pivs[l] != NULL) { memset(dr, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = bs->cf_32[pivs[l][COEFFS]]; const len_t os = pivs[l][PRELOOP]; const len_t len = pivs[l][LENGTH]; const len_t bi = pivs[l][BINDEX]; const len_t mh = pivs[l][MULT]; const hm_t * const ds = pivs[l] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { dr[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] = (int64_t)cfs[j]; dr[ds[j+1]] = (int64_t)cfs[j+1]; dr[ds[j+2]] = (int64_t)cfs[j+2]; dr[ds[j+3]] = (int64_t)cfs[j+3]; } free(pivs[l]); pivs[l] = NULL; pivs[l] = mat->tr[k--] = reduce_dense_row_by_known_pivots_sparse_ff_32( dr, mat, bs, pivs, sc, l, mh, bi, 0, st); } } if (free_basis != 0) { /* free now all polynomials in the basis and reset bs->ld to 0. */ free_basis_elements(bs); } free(mat->rr); mat->rr = NULL; mat->np = nrows; free(pivs); free(dr); } msolve-0.6.5/src/neogb/la_ff_8.c000066400000000000000000002361731456710632100163730ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "data.h" /* That's also enough if AVX512 is avaialable on the system */ #if defined HAVE_AVX2 #include #elif defined __aarch64__ #include #endif static inline cf8_t *normalize_dense_matrix_row_ff_8( cf8_t *row, const hm_t len, const uint32_t fc ) { len_t i; int64_t tmp1, tmp2, tmp3, tmp4; const hm_t os = len % UNROLL; const uint8_t fc8 = (uint8_t)fc; const uint8_t inv = mod_p_inverse_8(row[0], fc8); for (i = 1; i < os; ++i) { tmp1 = ((int64_t)row[i] * inv) % fc8; tmp1 += (tmp1 >> 63) & fc8; row[i] = (cf8_t)tmp1; } /* we need to set i to os since os < 1 is possible */ for (i = os; i < len; i += UNROLL) { tmp1 = ((int64_t)row[i] * inv) % fc8; tmp2 = ((int64_t)row[i+1] * inv) % fc8; tmp3 = ((int64_t)row[i+2] * inv) % fc8; tmp4 = ((int64_t)row[i+3] * inv) % fc8; tmp1 += (tmp1 >> 63) & fc8; tmp2 += (tmp2 >> 63) & fc8; tmp3 += (tmp3 >> 63) & fc8; tmp4 += (tmp4 >> 63) & fc8; row[i] = (cf8_t)tmp1; row[i+1] = (cf8_t)tmp2; row[i+2] = (cf8_t)tmp3; row[i+3] = (cf8_t)tmp4; } row[0] = 1; return row; } static inline cf8_t *normalize_sparse_matrix_row_ff_8( cf8_t *row, const len_t os, const len_t len, const uint32_t fc ) { len_t i; const uint8_t fc8 = (uint8_t)fc; const uint8_t inv = mod_p_inverse_8(row[0], fc8); for (i = 0; i < os; ++i) { row[i] = (cf8_t)(((uint16_t)row[i] * inv) % fc8); } /* we need to set i to os since os < 1 is possible */ for (i = os; i < len; i += UNROLL) { row[i] = (cf8_t)(((uint16_t)row[i] * inv) % fc8); row[i+1] = (cf8_t)(((uint16_t)row[i+1] * inv) % fc8); row[i+2] = (cf8_t)(((uint16_t)row[i+2] * inv) % fc8); row[i+3] = (cf8_t)(((uint16_t)row[i+3] * inv) % fc8); } row[0] = 1; return row; } static hm_t *reduce_dense_row_by_known_pivots_sparse_ff_8( int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t * const * const pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const hm_t tmp_pos, /* position of new coeffs array in tmpcf */ const len_t mh, /* multiplier hash for tracing */ const len_t bi, /* basis index of generating element */ const len_t tr, /* trace data? */ const uint32_t fc ) { hi_t i, j, k; hm_t *dts; cf8_t *cfs; int64_t np = -1; const int64_t mod = (int64_t)fc; const len_t ncols = mat->nc; const len_t ncl = mat->ncl; cf8_t * const * const mcf = mat->cf_8; rba_t *rba; if (tr > 0) { rba = mat->rba[tmp_pos]; } else { rba = NULL; } #if defined HAVE_AVX512_F __m512i mask1 = _mm512_set1_epi64(0x000000000000FFFF); __m512i mask2 = _mm512_set1_epi64(0x00000000FFFF0000); __m512i mask3 = _mm512_set1_epi64(0x0000FFFF00000000); __m512i mask4 = _mm512_set1_epi64(0xFFFF000000000000); __m512i mask8 = _mm512_set1_epi16(0x00FF); int64_t res[8] __attribute__((aligned(64))); __m512i redv, mulv, prod, drv, resv; #elif defined HAVE_AVX2 __m256i mask1 = _mm256_set1_epi64x(0x000000000000FFFF); __m256i mask2 = _mm256_set1_epi64x(0x00000000FFFF0000); __m256i mask3 = _mm256_set1_epi64x(0x0000FFFF00000000); __m256i mask4 = _mm256_set1_epi64x(0xFFFF000000000000); __m256i mask8 = _mm256_set1_epi16(0x00FF); int64_t res[4] __attribute__((aligned(32))); __m256i redv, mulv, prod, drv, resv; #elif defined __aarch64__ uint64_t tmp[2] __attribute__((aligned(32))); uint16x8_t prodv; uint32x4_t prodvl, prodvh; uint8x16_t redv; uint64x2_t drv, resv; #endif k = 0; for (i = dpiv; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { np = i; } k++; continue; } /* found reducer row, get multiplier */ const uint32_t mul= (uint32_t)(fc - dr[i]); dts = pivs[i]; if (i < ncl) { /* set corresponding bit of reducer in reducer bit array */ if (tr > 0) { rba[i/32] |= 1U << (i % 32); } } cfs = mcf[dts[COEFFS]]; #if defined HAVE_AVX512_F const uint16_t mul8 = (uint16_t)(fc - dr[i]); mulv = _mm512_set1_epi16(mul8); const len_t len = dts[LENGTH]; const len_t os = len % 64; const hm_t * const ds = dts + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += 64) { redv = _mm512_loadu_si512((__m512i*)(cfs+j)); /* first 16 mult-adds -- lower */ prod = _mm512_mullo_epi16(mulv,_mm512_and_si512(redv, mask8)); drv = _mm512_setr_epi64( dr[ds[j]], dr[ds[j+8]], dr[ds[j+16]], dr[ds[j+24]], dr[ds[j+32]], dr[ds[j+40]], dr[ds[j+48]], dr[ds[j+56]]); resv = _mm512_add_epi64(drv, _mm512_and_si512(prod, mask1)); _mm512_store_si512((__m512i*)(res),resv); dr[ds[j]] = res[0]; dr[ds[j+8]] = res[1]; dr[ds[j+16]] = res[2]; dr[ds[j+24]] = res[3]; dr[ds[j+32]] = res[4]; dr[ds[j+40]] = res[5]; dr[ds[j+48]] = res[6]; dr[ds[j+56]] = res[7]; drv = _mm512_setr_epi64( dr[ds[j+2]], dr[ds[j+10]], dr[ds[j+18]], dr[ds[j+26]], dr[ds[j+34]], dr[ds[j+42]], dr[ds[j+50]], dr[ds[j+58]]); resv = _mm512_add_epi64(drv, _mm512_srli_epi64(_mm512_and_si512(prod, mask2), 16)); _mm512_store_si512((__m512i*)(res),resv); dr[ds[j+2]] = res[0]; dr[ds[j+10]] = res[1]; dr[ds[j+18]] = res[2]; dr[ds[j+26]] = res[3]; dr[ds[j+34]] = res[4]; dr[ds[j+42]] = res[5]; dr[ds[j+50]] = res[6]; dr[ds[j+58]] = res[7]; drv = _mm512_setr_epi64( dr[ds[j+4]], dr[ds[j+12]], dr[ds[j+20]], dr[ds[j+28]], dr[ds[j+36]], dr[ds[j+44]], dr[ds[j+52]], dr[ds[j+60]]); resv = _mm512_add_epi64(drv, _mm512_srli_epi64(_mm512_and_si512(prod, mask3), 32)); _mm512_store_si512((__m512i*)(res),resv); dr[ds[j+4]] = res[0]; dr[ds[j+12]] = res[1]; dr[ds[j+20]] = res[2]; dr[ds[j+28]] = res[3]; dr[ds[j+36]] = res[4]; dr[ds[j+44]] = res[5]; dr[ds[j+52]] = res[6]; dr[ds[j+60]] = res[7]; drv = _mm512_setr_epi64( dr[ds[j+6]], dr[ds[j+14]], dr[ds[j+22]], dr[ds[j+30]], dr[ds[j+38]], dr[ds[j+46]], dr[ds[j+54]], dr[ds[j+62]]); resv = _mm512_add_epi64(drv, _mm512_srli_epi64(_mm512_and_si512(prod, mask4), 48)); _mm512_store_si512((__m512i*)(res),resv); dr[ds[j+6]] = res[0]; dr[ds[j+14]] = res[1]; dr[ds[j+22]] = res[2]; dr[ds[j+30]] = res[3]; dr[ds[j+38]] = res[4]; dr[ds[j+46]] = res[5]; dr[ds[j+54]] = res[6]; dr[ds[j+62]] = res[7]; /* second 16 mult-adds -- higher */ prod = _mm512_mullo_epi16(mulv, _mm512_srli_epi16(redv, 8)); drv = _mm512_setr_epi64( dr[ds[j+1]], dr[ds[j+9]], dr[ds[j+17]], dr[ds[j+25]], dr[ds[j+33]], dr[ds[j+41]], dr[ds[j+49]], dr[ds[j+57]]); resv = _mm512_add_epi64(drv, _mm512_and_si512(prod, mask1)); _mm512_store_si512((__m512i*)(res),resv); dr[ds[j+1]] = res[0]; dr[ds[j+9]] = res[1]; dr[ds[j+17]] = res[2]; dr[ds[j+25]] = res[3]; dr[ds[j+33]] = res[4]; dr[ds[j+41]] = res[5]; dr[ds[j+49]] = res[6]; dr[ds[j+57]] = res[7]; drv = _mm512_setr_epi64( dr[ds[j+3]], dr[ds[j+11]], dr[ds[j+19]], dr[ds[j+27]], dr[ds[j+35]], dr[ds[j+43]], dr[ds[j+51]], dr[ds[j+59]]); resv = _mm512_add_epi64(drv, _mm512_srli_epi64(_mm512_and_si512(prod, mask2), 16)); _mm512_store_si512((__m512i*)(res),resv); dr[ds[j+3]] = res[0]; dr[ds[j+11]] = res[1]; dr[ds[j+19]] = res[2]; dr[ds[j+27]] = res[3]; dr[ds[j+35]] = res[4]; dr[ds[j+43]] = res[5]; dr[ds[j+51]] = res[6]; dr[ds[j+59]] = res[7]; drv = _mm512_setr_epi64( dr[ds[j+5]], dr[ds[j+13]], dr[ds[j+21]], dr[ds[j+29]], dr[ds[j+37]], dr[ds[j+45]], dr[ds[j+53]], dr[ds[j+61]]); resv = _mm512_add_epi64(drv, _mm512_srli_epi64(_mm512_and_si512(prod, mask3), 32)); _mm512_store_si512((__m512i*)(res),resv); dr[ds[j+5]] = res[0]; dr[ds[j+13]] = res[1]; dr[ds[j+21]] = res[2]; dr[ds[j+29]] = res[3]; dr[ds[j+37]] = res[4]; dr[ds[j+45]] = res[5]; dr[ds[j+53]] = res[6]; dr[ds[j+61]] = res[7]; drv = _mm512_setr_epi64( dr[ds[j+7]], dr[ds[j+15]], dr[ds[j+23]], dr[ds[j+31]], dr[ds[j+39]], dr[ds[j+47]], dr[ds[j+55]], dr[ds[j+63]]); resv = _mm512_add_epi64(drv, _mm512_srli_epi64(_mm512_and_si512(prod, mask4), 48)); _mm512_store_si512((__m512i*)(res),resv); dr[ds[j+7]] = res[0]; dr[ds[j+15]] = res[1]; dr[ds[j+23]] = res[2]; dr[ds[j+31]] = res[3]; dr[ds[j+39]] = res[4]; dr[ds[j+47]] = res[5]; dr[ds[j+55]] = res[6]; dr[ds[j+63]] = res[7]; } #elif defined HAVE_AVX2 const uint16_t mul8 = (uint16_t)(fc - dr[i]); mulv = _mm256_set1_epi16(mul8); const len_t len = dts[LENGTH]; const len_t os = len % 32; const hm_t * const ds = dts + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += 32) { redv = _mm256_loadu_si256((__m256i*)(cfs+j)); /* first 16 mult-adds -- lower */ prod = _mm256_mullo_epi16(mulv,_mm256_and_si256(redv, mask8)); drv = _mm256_setr_epi64x( dr[ds[j]], dr[ds[j+8]], dr[ds[j+16]], dr[ds[j+24]]); resv = _mm256_add_epi64(drv, _mm256_and_si256(prod, mask1)); _mm256_store_si256((__m256i*)(res),resv); dr[ds[j]] = res[0]; dr[ds[j+8]] = res[1]; dr[ds[j+16]] = res[2]; dr[ds[j+24]] = res[3]; drv = _mm256_setr_epi64x( dr[ds[j+2]], dr[ds[j+10]], dr[ds[j+18]], dr[ds[j+26]]); resv = _mm256_add_epi64(drv, _mm256_srli_epi64(_mm256_and_si256(prod, mask2), 16)); _mm256_store_si256((__m256i*)(res),resv); dr[ds[j+2]] = res[0]; dr[ds[j+10]] = res[1]; dr[ds[j+18]] = res[2]; dr[ds[j+26]] = res[3]; drv = _mm256_setr_epi64x( dr[ds[j+4]], dr[ds[j+12]], dr[ds[j+20]], dr[ds[j+28]]); resv = _mm256_add_epi64(drv, _mm256_srli_epi64(_mm256_and_si256(prod, mask3), 32)); _mm256_store_si256((__m256i*)(res),resv); dr[ds[j+4]] = res[0]; dr[ds[j+12]] = res[1]; dr[ds[j+20]] = res[2]; dr[ds[j+28]] = res[3]; drv = _mm256_setr_epi64x( dr[ds[j+6]], dr[ds[j+14]], dr[ds[j+22]], dr[ds[j+30]]); resv = _mm256_add_epi64(drv, _mm256_srli_epi64(_mm256_and_si256(prod, mask4), 48)); _mm256_store_si256((__m256i*)(res),resv); dr[ds[j+6]] = res[0]; dr[ds[j+14]] = res[1]; dr[ds[j+22]] = res[2]; dr[ds[j+30]] = res[3]; /* second 16 mult-adds -- higher */ prod = _mm256_mullo_epi16(mulv, _mm256_srli_epi16(redv, 8)); drv = _mm256_setr_epi64x( dr[ds[j+1]], dr[ds[j+9]], dr[ds[j+17]], dr[ds[j+25]]); resv = _mm256_add_epi64(drv, _mm256_and_si256(prod, mask1)); _mm256_store_si256((__m256i*)(res),resv); dr[ds[j+1]] = res[0]; dr[ds[j+9]] = res[1]; dr[ds[j+17]] = res[2]; dr[ds[j+25]] = res[3]; drv = _mm256_setr_epi64x( dr[ds[j+3]], dr[ds[j+11]], dr[ds[j+19]], dr[ds[j+27]]); resv = _mm256_add_epi64(drv, _mm256_srli_epi64(_mm256_and_si256(prod, mask2), 16)); _mm256_store_si256((__m256i*)(res),resv); dr[ds[j+3]] = res[0]; dr[ds[j+11]] = res[1]; dr[ds[j+19]] = res[2]; dr[ds[j+27]] = res[3]; drv = _mm256_setr_epi64x( dr[ds[j+5]], dr[ds[j+13]], dr[ds[j+21]], dr[ds[j+29]]); resv = _mm256_add_epi64(drv, _mm256_srli_epi64(_mm256_and_si256(prod, mask3), 32)); _mm256_store_si256((__m256i*)(res),resv); dr[ds[j+5]] = res[0]; dr[ds[j+13]] = res[1]; dr[ds[j+21]] = res[2]; dr[ds[j+29]] = res[3]; drv = _mm256_setr_epi64x( dr[ds[j+7]], dr[ds[j+15]], dr[ds[j+23]], dr[ds[j+31]]); resv = _mm256_add_epi64(drv, _mm256_srli_epi64(_mm256_and_si256(prod, mask4), 48)); _mm256_store_si256((__m256i*)(res),resv); dr[ds[j+7]] = res[0]; dr[ds[j+15]] = res[1]; dr[ds[j+23]] = res[2]; dr[ds[j+31]] = res[3]; } #elif defined __aarch64__ const len_t len = dts[LENGTH]; const len_t os = len % 16; const hm_t * const ds = dts + OFFSET; const cf8_t mul8 = (cf8_t)(mod - dr[i]); const uint8x8_t mulv = vmov_n_u8(mul8); for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += 16) { redv = vld1q_u8(cfs+j); prodv = vmull_u8(vget_low_u8(redv), mulv); prodvl = vmovl_u16(vget_low_u16(prodv)); tmp[0] = (uint64_t)dr[ds[j]]; tmp[1] = (uint64_t)dr[ds[j+1]]; drv = vld1q_u64(tmp); resv = vaddw_u32(drv, vget_low_u32(prodvl)); vst1q_u64(tmp, resv); dr[ds[j]] = (int64_t)tmp[0]; dr[ds[j+1]] = (int64_t)tmp[1]; tmp[0] = (uint64_t)dr[ds[j+2]]; tmp[1] = (uint64_t)dr[ds[j+3]]; drv = vld1q_u64(tmp); resv = vaddw_u32(drv, vget_high_u32(prodvl)); vst1q_u64(tmp, resv); dr[ds[j+2]] = (int64_t)tmp[0]; dr[ds[j+3]] = (int64_t)tmp[1]; prodvh = vmovl_u16(vget_high_u16(prodv)); tmp[0] = (uint64_t)dr[ds[j+4]]; tmp[1] = (uint64_t)dr[ds[j+5]]; drv = vld1q_u64(tmp); resv = vaddw_u32(drv, vget_low_u32(prodvh)); vst1q_u64(tmp, resv); dr[ds[j+4]] = (int64_t)tmp[0]; dr[ds[j+5]] = (int64_t)tmp[1]; tmp[0] = (uint64_t)dr[ds[j+6]]; tmp[1] = (uint64_t)dr[ds[j+7]]; drv = vld1q_u64(tmp); resv = vaddw_u32(drv, vget_high_u32(prodvh)); vst1q_u64(tmp, resv); dr[ds[j+6]] = (int64_t)tmp[0]; dr[ds[j+7]] = (int64_t)tmp[1]; prodv = vmull_u8(vget_high_u8(redv), mulv); prodvl = vmovl_u16(vget_low_u16(prodv)); tmp[0] = (uint64_t)dr[ds[j+8]]; tmp[1] = (uint64_t)dr[ds[j+9]]; drv = vld1q_u64(tmp); resv = vaddw_u32(drv, vget_low_u32(prodvl)); vst1q_u64(tmp, resv); dr[ds[j+8]] = (int64_t)tmp[0]; dr[ds[j+9]] = (int64_t)tmp[1]; tmp[0] = (uint64_t)dr[ds[j+10]]; tmp[1] = (uint64_t)dr[ds[j+11]]; drv = vld1q_u64(tmp); resv = vaddw_u32(drv, vget_high_u32(prodvl)); vst1q_u64(tmp, resv); dr[ds[j+10]] = (int64_t)tmp[0]; dr[ds[j+11]] = (int64_t)tmp[1]; prodvh = vmovl_u16(vget_high_u16(prodv)); tmp[0] = (uint64_t)dr[ds[j+12]]; tmp[1] = (uint64_t)dr[ds[j+13]]; drv = vld1q_u64(tmp); resv = vaddw_u32(drv, vget_low_u32(prodvh)); vst1q_u64(tmp, resv); dr[ds[j+12]] = (int64_t)tmp[0]; dr[ds[j+13]] = (int64_t)tmp[1]; tmp[0] = (uint64_t)dr[ds[j+14]]; tmp[1] = (uint64_t)dr[ds[j+15]]; drv = vld1q_u64(tmp); resv = vaddw_u32(drv, vget_high_u32(prodvh)); vst1q_u64(tmp, resv); dr[ds[j+14]] = (int64_t)tmp[0]; dr[ds[j+15]] = (int64_t)tmp[1]; } #else const len_t os = dts[PRELOOP]; const len_t len = dts[LENGTH]; const hm_t * const ds = dts + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] += mul * cfs[j]; dr[ds[j+1]] += mul * cfs[j+1]; dr[ds[j+2]] += mul * cfs[j+2]; dr[ds[j+3]] += mul * cfs[j+3]; } #endif dr[i] = 0; } if (k == 0) { return NULL; } hm_t *row = (hm_t *)malloc((unsigned long)(k+OFFSET) * sizeof(hm_t)); cf8_t *cf = (cf8_t *)malloc((unsigned long)(k) * sizeof(cf8_t)); j = 0; hm_t *rs = row + OFFSET; for (i = ncl; i < ncols; ++i) { if (dr[i] != 0) { rs[j] = (hm_t)i; cf[j] = (cf8_t)dr[i]; j++; } } row[BINDEX] = bi; row[MULT] = mh; row[COEFFS] = tmp_pos; row[PRELOOP] = j % UNROLL; row[LENGTH] = j; mat->cf_8[tmp_pos] = cf; return row; } static hm_t *trace_reduce_dense_row_by_known_pivots_sparse_ff_8( rba_t *rba, int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t * const * const pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const hm_t tmp_pos, /* position of new coeffs array in tmpcf */ const len_t mh, /* multiplier hash for tracing */ const len_t bi, /* basis index of generating element */ const uint32_t fc ) { hi_t i, j, k; hm_t *dts; cf8_t *cfs; int64_t np = -1; const int64_t mod = (int64_t)fc; const len_t ncols = mat->nc; const len_t ncl = mat->ncl; cf8_t * const * const mcf = mat->cf_8; k = 0; for (i = dpiv; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { np = i; } k++; continue; } /* found reducer row, get multiplier */ const uint32_t mul= (uint32_t)(fc - dr[i]); dts = pivs[i]; if (i < ncl) { cfs = bs->cf_8[dts[COEFFS]]; /* set corresponding bit of reducer in reducer bit array */ rba[i/32] |= 1U << (i % 32); } else { cfs = mcf[dts[COEFFS]]; } const len_t os = dts[PRELOOP]; const len_t len = dts[LENGTH]; const hm_t * const ds = dts + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] += mul * cfs[j]; dr[ds[j+1]] += mul * cfs[j+1]; dr[ds[j+2]] += mul * cfs[j+2]; dr[ds[j+3]] += mul * cfs[j+3]; } dr[i] = 0; } if (k == 0) { return NULL; } hm_t *row = (hm_t *)malloc((unsigned long)(k+OFFSET) * sizeof(hm_t)); cf8_t *cf = (cf8_t *)malloc((unsigned long)(k) * sizeof(cf8_t)); j = 0; hm_t *rs = row + OFFSET; for (i = ncl; i < ncols; ++i) { if (dr[i] != 0) { rs[j] = (hm_t)i; cf[j] = (cf8_t)dr[i]; j++; } } row[BINDEX] = bi; row[MULT] = mh; row[COEFFS] = tmp_pos; row[PRELOOP] = j % UNROLL; row[LENGTH] = j; mat->cf_8[tmp_pos] = cf; return row; } static cf8_t *reduce_dense_row_by_all_pivots_ff_8( int64_t *dr, mat_t *mat, const bs_t * const bs, len_t *pc, hm_t *const * const pivs, cf8_t *const * const dpivs, const uint32_t fc ) { hi_t i, j, k, l; const int64_t mod = (int64_t)fc; len_t np = -1; cf8_t *red; const len_t ncl = mat->ncl; const len_t ncols = mat->nc; /* step 1: reduce by sparse known pivots */ for (i = *pc; i < ncl; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { continue; } /* found reducer row, get multiplier */ const uint32_t mul= (uint32_t)(fc - dr[i]); const cf8_t *cfs = bs->cf_8[pivs[i][COEFFS]]; const len_t os = pivs[i][PRELOOP]; const len_t len = pivs[i][LENGTH]; const hm_t * const ds = pivs[i] + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] += mul * cfs[j]; dr[ds[j+1]] += mul * cfs[j+1]; dr[ds[j+2]] += mul * cfs[j+2]; dr[ds[j+3]] += mul * cfs[j+3]; } dr[i] = 0; } k = 0; /* step 2: reduce by new dense pivots */ for (i = ncl; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (dpivs[i-ncl] == NULL) { if (np == -1) { np = i; } k++; continue; } red = dpivs[i-ncl]; const uint32_t mul= (uint32_t)(fc - dr[i]); const len_t os = (ncols - i) % UNROLL; for (l = 0, j = i; l < os; ++l, ++j) { dr[j] += mul * red[l]; } for (; j < ncols; l += UNROLL, j += UNROLL) { dr[j] += mul * red[l]; dr[j+1] += mul * red[l+1]; dr[j+2] += mul * red[l+2]; dr[j+3] += mul * red[l+3]; } } if (k == 0) { *pc = -1; return NULL; } cf8_t *row = (cf8_t *)calloc((unsigned long)(ncols-np), sizeof(cf8_t)); for (i = np; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } row[i-np] = (cf8_t)dr[i]; } if (row[0] != 1) { row = normalize_dense_matrix_row_ff_8(row, ncols-np, fc); } *pc = np - ncl; return row; } static cf8_t *reduce_dense_row_by_old_pivots_ff_8( int64_t *dr, mat_t *mat, const bs_t * const bs, hm_t *const * const pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const uint32_t fc ) { hi_t i, j; const int64_t mod = (int64_t)fc; const len_t ncols = mat->nc; const len_t ncl = mat->ncl; const len_t ncr = mat->ncr; for (i = dpiv; i < ncl; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { continue; } /* found reducer row, get multiplier */ const uint32_t mul= (uint32_t)(fc - dr[i]); const cf8_t *cfs = bs->cf_8[pivs[i][COEFFS]]; const len_t os = pivs[i][PRELOOP]; const len_t len = pivs[i][LENGTH]; const hm_t * const ds = pivs[i] + OFFSET; for (j = 0; j < os; ++j) { dr[ds[j]] += mul * cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] += mul * cfs[j]; dr[ds[j+1]] += mul * cfs[j+1]; dr[ds[j+2]] += mul * cfs[j+2]; dr[ds[j+3]] += mul * cfs[j+3]; } dr[i] = 0; } /* store a dense row for further dense gaussian elimination */ cf8_t *row = (cf8_t *)calloc( (unsigned long)(ncr), sizeof(cf8_t)); j = 0; for (i = ncl; i < ncols; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; if (dr[i] != 0) { j++; row[i-ncl] = (cf8_t)dr[i]; } } } if (j == 0) { free(row); row = NULL; } return row; } static cf8_t *reduce_dense_row_by_dense_new_pivots_ff_8( int64_t *dr, len_t *pc, cf8_t * const * const pivs, const len_t ncr, const uint32_t fc ) { hi_t i, j, k, l; len_t np = -1; const int64_t mod = (int64_t)fc; for (k = 0, i = *pc; i < ncr; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } if (dr[i] == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { np = i; } k++; continue; } const uint32_t mul= (uint32_t)(fc - dr[i]); const len_t os = (ncr - i) % UNROLL; for (l = 0, j = i; l < os; ++l, ++j) { dr[j] += mul * pivs[i][l]; } for (; j < ncr; l += UNROLL, j += UNROLL) { dr[j] += mul * pivs[i][l]; dr[j+1] += mul * pivs[i][l+1]; dr[j+2] += mul * pivs[i][l+2]; dr[j+3] += mul * pivs[i][l+3]; } } if (k == 0) { *pc = -1; return NULL; } cf8_t *row = (cf8_t *)calloc((unsigned long)(ncr-np), sizeof(cf8_t)); for (i = np; i < ncr; ++i) { if (dr[i] != 0) { dr[i] = dr[i] % mod; } row[i-np] = (cf8_t)dr[i]; } if (row[0] != 1) { row = normalize_dense_matrix_row_ff_8(row, ncr-np, fc); } *pc = np; return row; } static void probabilistic_sparse_reduced_echelon_form_ff_8( mat_t *mat, const bs_t * const bs, md_t *st ) { len_t i = 0, j, k, l, m; const len_t ncols = mat->nc; const len_t nrl = mat->nrl; const len_t ncr = mat->ncr; const len_t ncl = mat->ncl; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); j = nrl; for (i = 0; i < mat->nru; ++i) { mat->cf_8[j] = bs->cf_8[mat->rr[i][COEFFS]]; mat->rr[i][COEFFS] = j; ++j; } /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; const uint32_t fc = st->fc; const int64_t mod2 = (int64_t)fc * fc; /* compute rows per block */ const len_t nb = (len_t)(floor(sqrt(nrl/3)))+1; const len_t rem = (nrl % nb == 0) ? 0 : 1; const len_t rpb = (nrl / nb) + rem; int64_t *dr = (int64_t *)malloc( (unsigned long)(st->nthrds * ncols) * sizeof(int64_t)); int64_t *mul = (int64_t *)malloc( (unsigned long)(st->nthrds * rpb) * sizeof(int64_t)); /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ #pragma omp parallel for num_threads(st->nthrds) \ private(i, j, k, l, m) \ schedule(dynamic) for (i = 0; i < nb; ++i) { int64_t *drl = dr + (omp_get_thread_num() * ncols); int64_t *mull = mul + (omp_get_thread_num() * rpb); const int32_t nbl = (int32_t) (nrl > (i+1)*rpb ? (i+1)*rpb : nrl); const int32_t nrbl = (int32_t) (nbl - i*rpb); if (nrbl != 0) { hm_t *npiv = NULL; cf8_t *cfs; /* starting column, offset, coefficient array position in tmpcf */ hm_t sc, cfp; len_t bctr = 0; while (bctr < nrbl) { cfp = bctr + i*rpb; sc = 0; /* fill random value array */ for (j = 0; j < nrbl; ++j) { mull[j] = (int64_t)rand() % fc; } /* generate one dense row as random linear combination * of the rows of the block */ memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); for (k = 0, m = i*rpb; m < nbl; ++k, ++m) { npiv = upivs[m]; cfs = bs->cf_8[npiv[COEFFS]]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const hm_t * const ds = npiv + OFFSET; sc = sc < ds[0] ? sc : ds[0]; for (l = 0; l < os; ++l) { drl[ds[l]] -= mull[k] * cfs[l]; drl[ds[l]] += (drl[ds[l]] >> 63) & mod2; } for (; l < len; l += UNROLL) { drl[ds[l]] -= mull[k] * cfs[l]; drl[ds[l]] += (drl[ds[l]] >> 63) & mod2; drl[ds[l+1]] -= mull[k] * cfs[l+1]; drl[ds[l+1]] += (drl[ds[l+1]] >> 63) & mod2; drl[ds[l+2]] -= mull[k] * cfs[l+2]; drl[ds[l+2]] += (drl[ds[l+2]] >> 63) & mod2; drl[ds[l+3]] -= mull[k] * cfs[l+3]; drl[ds[l+3]] += (drl[ds[l+3]] >> 63) & mod2; } } k = 0; cfs = NULL; npiv = NULL; /* do the reduction */ do { free(cfs); cfs = NULL; free(npiv); npiv = NULL; npiv = reduce_dense_row_by_known_pivots_sparse_ff_8( drl, mat, bs, pivs, sc, cfp, 0, 0, 0, st->fc); if (!npiv) { bctr = nrbl; break; } /* normalize coefficient array * NOTE: this has to be done here, otherwise the reduction may * lead to wrong results in a parallel computation since other * threads might directly use the new pivot once it is synced. */ if (mat->cf_8[npiv[COEFFS]][0] != 1) { normalize_sparse_matrix_row_ff_8( mat->cf_8[npiv[COEFFS]], npiv[PRELOOP], npiv[LENGTH], st->fc); } cfs = mat->cf_8[npiv[COEFFS]]; sc = npiv[OFFSET]; k = __sync_bool_compare_and_swap(&pivs[npiv[OFFSET]], NULL, npiv); } while (!k); bctr++; } for (j = i*rpb; j < nbl; ++j) { free(upivs[j]); upivs[j] = NULL; } } } free(mul); mul = NULL; /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { free(pivs[i]); pivs[i] = NULL; } len_t npivs = 0; /* number of new pivots */ dr = realloc(dr, (unsigned long)ncols * sizeof(uint64_t)); mat->tr = realloc(mat->tr, (unsigned long)ncr * sizeof(hm_t *)); /* interreduce new pivots */ cf8_t *cfs; /* starting column, coefficient array position in tmpcf */ hm_t sc, cfp; for (i = 0; i < ncr; ++i) { k = ncols-1-i; if (pivs[k]) { memset(dr, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = mat->cf_8[pivs[k][COEFFS]]; cfp = pivs[k][COEFFS]; const len_t bi = pivs[k][BINDEX]; const len_t mh = pivs[k][MULT]; const len_t os = pivs[k][PRELOOP]; const len_t len = pivs[k][LENGTH]; const hm_t * const ds = pivs[k] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { dr[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] = (int64_t)cfs[j]; dr[ds[j+1]] = (int64_t)cfs[j+1]; dr[ds[j+2]] = (int64_t)cfs[j+2]; dr[ds[j+3]] = (int64_t)cfs[j+3]; } free(pivs[k]); free(cfs); pivs[k] = NULL; pivs[k] = mat->tr[npivs++] = reduce_dense_row_by_known_pivots_sparse_ff_8( dr, mat, bs, pivs, sc, cfp, mh, bi, 0, st->fc); } } free(mat->rr); mat->rr = NULL; free(pivs); pivs = NULL; free(dr); dr = NULL; mat->tr = realloc(mat->tr, (unsigned long)npivs * sizeof(hi_t *)); st->np = mat->np = mat->nr = mat->sz = npivs; } static int exact_application_sparse_reduced_echelon_form_ff_8( mat_t *mat, const bs_t * const bs, md_t *st ) { len_t i = 0, j, k; hi_t sc = 0; /* starting column */ const len_t ncols = mat->nc; const len_t nrl = mat->nrl; const len_t ncr = mat->ncr; const len_t ncl = mat->ncl; const int32_t nthrds = st->in_final_reduction_step == 1 ? 1 : st->nthrds; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; int64_t *dr = (int64_t *)malloc( (unsigned long)(nthrds * ncols) * sizeof(int64_t)); /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ int flag = 1; #pragma omp parallel for num_threads(nthrds) \ private(i, j, k, sc) \ schedule(dynamic) for (i = 0; i < nrl; ++i) { if (flag == 1) { int64_t *drl = dr + (omp_get_thread_num() * ncols); hm_t *npiv = upivs[i]; cf8_t *cfs = bs->cf_8[npiv[COEFFS]]; const len_t bi = npiv[BINDEX]; const len_t mh = npiv[MULT]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const hm_t * const ds = npiv + OFFSET; k = 0; memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); for (j = 0; j < os; ++j) { drl[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { drl[ds[j]] = (int64_t)cfs[j]; drl[ds[j+1]] = (int64_t)cfs[j+1]; drl[ds[j+2]] = (int64_t)cfs[j+2]; drl[ds[j+3]] = (int64_t)cfs[j+3]; } cfs = NULL; do { sc = npiv[OFFSET]; free(npiv); free(cfs); npiv = mat->tr[i] = reduce_dense_row_by_known_pivots_sparse_ff_8( drl, mat, bs, pivs, sc, i, mh, bi, 0, st->fc); if (!npiv) { fprintf(stderr, "Unlucky prime detected, row reduced to zero."); flag = 0; } /* normalize coefficient array * NOTE: this has to be done here, otherwise the reduction may * lead to wrong results in a parallel computation since other * threads might directly use the new pivot once it is synced. */ if (mat->cf_8[npiv[COEFFS]][0] != 1) { normalize_sparse_matrix_row_ff_8( mat->cf_8[npiv[COEFFS]], npiv[PRELOOP], npiv[LENGTH], st->fc); } k = __sync_bool_compare_and_swap(&pivs[npiv[OFFSET]], NULL, npiv); cfs = mat->cf_8[npiv[COEFFS]]; } while (!k); } } /* unlucky prime found */ if (flag == 0) { return 1; } /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { free(pivs[i]); pivs[i] = NULL; } len_t npivs = 0; /* number of new pivots */ dr = realloc(dr, (unsigned long)ncols * sizeof(uint64_t)); mat->tr = realloc(mat->tr, (unsigned long)ncr * sizeof(hm_t *)); /* interreduce new pivots */ cf8_t *cfs; hm_t cf_array_pos; for (i = 0; i < ncr; ++i) { k = ncols-1-i; if (pivs[k]) { memset(dr, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = mat->cf_8[pivs[k][COEFFS]]; cf_array_pos = pivs[k][COEFFS]; const len_t bi = pivs[k][BINDEX]; const len_t mh = pivs[k][MULT]; const len_t os = pivs[k][PRELOOP]; const len_t len = pivs[k][LENGTH]; const hm_t * const ds = pivs[k] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { dr[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] = (int64_t)cfs[j]; dr[ds[j+1]] = (int64_t)cfs[j+1]; dr[ds[j+2]] = (int64_t)cfs[j+2]; dr[ds[j+3]] = (int64_t)cfs[j+3]; } free(pivs[k]); free(cfs); pivs[k] = NULL; pivs[k] = mat->tr[npivs++] = reduce_dense_row_by_known_pivots_sparse_ff_8( dr, mat, bs, pivs, sc, cf_array_pos, mh, bi, 0, st->fc); } } free(pivs); pivs = NULL; free(dr); dr = NULL; mat->tr = realloc(mat->tr, (unsigned long)npivs * sizeof(hi_t *)); st->np = mat->np = mat->nr = mat->sz = npivs; return 0; } static void exact_trace_sparse_reduced_echelon_form_ff_8( trace_t *trace, mat_t *mat, const bs_t * const bs, md_t *st ) { len_t i = 0, j, k; hi_t sc = 0; /* starting column */ const len_t ncols = mat->nc; const len_t nrl = mat->nrl; const len_t ncr = mat->ncr; const len_t ncl = mat->ncl; const int32_t nthrds = st->in_final_reduction_step == 1 ? 1 : st->nthrds; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; int64_t *dr = (int64_t *)malloc( (unsigned long)(nthrds * ncols) * sizeof(int64_t)); /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ #pragma omp parallel for num_threads(nthrds) \ private(i, j, k, sc) \ schedule(dynamic) for (i = 0; i < nrl; ++i) { int64_t *drl = dr + (omp_get_thread_num() * ncols); hm_t *npiv = upivs[i]; rba_t *rba = mat->rba[i]; cf8_t *cfs = bs->cf_8[npiv[COEFFS]]; const len_t bi = upivs[i][BINDEX]; const len_t mh = upivs[i][MULT]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const hm_t * const ds = npiv + OFFSET; k = 0; memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); for (j = 0; j < os; ++j) { drl[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { drl[ds[j]] = (int64_t)cfs[j]; drl[ds[j+1]] = (int64_t)cfs[j+1]; drl[ds[j+2]] = (int64_t)cfs[j+2]; drl[ds[j+3]] = (int64_t)cfs[j+3]; } cfs = NULL; do { sc = npiv[OFFSET]; free(npiv); free(cfs); npiv = mat->tr[i] = trace_reduce_dense_row_by_known_pivots_sparse_ff_8( rba, drl, mat, bs, pivs, sc, i, mh, bi, st->fc); if (!npiv) { break; } /* normalize coefficient array * NOTE: this has to be done here, otherwise the reduction may * lead to wrong results in a parallel computation since other * threads might directly use the new pivot once it is synced. */ if (mat->cf_8[npiv[COEFFS]][0] != 1) { normalize_sparse_matrix_row_ff_8( mat->cf_8[npiv[COEFFS]], npiv[PRELOOP], npiv[LENGTH], st->fc); } k = __sync_bool_compare_and_swap(&pivs[npiv[OFFSET]], NULL, npiv); cfs = mat->cf_8[npiv[COEFFS]]; } while (!k); } /* construct the trace */ construct_trace(trace, mat); /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { free(pivs[i]); pivs[i] = NULL; } len_t npivs = 0; /* number of new pivots */ dr = realloc(dr, (unsigned long)ncols * sizeof(uint64_t)); mat->tr = realloc(mat->tr, (unsigned long)ncr * sizeof(hm_t *)); /* interreduce new pivots */ cf8_t *cfs; hm_t cf_array_pos; for (i = 0; i < ncr; ++i) { k = ncols-1-i; if (pivs[k]) { memset(dr, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = mat->cf_8[pivs[k][COEFFS]]; cf_array_pos = pivs[k][COEFFS]; const len_t bi = pivs[k][BINDEX]; const len_t mh = pivs[k][MULT]; const len_t os = pivs[k][PRELOOP]; const len_t len = pivs[k][LENGTH]; const hm_t * const ds = pivs[k] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { dr[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] = (int64_t)cfs[j]; dr[ds[j+1]] = (int64_t)cfs[j+1]; dr[ds[j+2]] = (int64_t)cfs[j+2]; dr[ds[j+3]] = (int64_t)cfs[j+3]; } free(pivs[k]); free(cfs); pivs[k] = NULL; pivs[k] = mat->tr[npivs++] = reduce_dense_row_by_known_pivots_sparse_ff_8( dr, mat, bs, pivs, sc, cf_array_pos, mh, bi, 0, st->fc); } } free(pivs); pivs = NULL; free(dr); dr = NULL; mat->tr = realloc(mat->tr, (unsigned long)npivs * sizeof(hi_t *)); st->np = mat->np = mat->nr = mat->sz = npivs; } static void exact_sparse_reduced_echelon_form_ff_8( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { len_t i = 0, j, k; hi_t sc = 0; /* starting column */ const len_t ncols = mat->nc; const len_t nrl = mat->nrl; const len_t ncr = mat->ncr; const len_t ncl = mat->ncl; const int32_t nthrds = st->in_final_reduction_step == 1 ? 1 : st->nthrds; len_t bad_prime = 0; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); if (st->in_final_reduction_step == 0) { memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); } else { for (i = 0; i < mat->nru; ++i) { pivs[mat->rr[i][OFFSET]] = mat->rr[i]; } } j = nrl; for (i = 0; i < mat->nru; ++i) { mat->cf_8[j] = bs->cf_8[mat->rr[i][COEFFS]]; mat->rr[i][COEFFS] = j; ++j; } /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; int64_t *dr = (int64_t *)malloc( (unsigned long)(nthrds * ncols) * sizeof(int64_t)); /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ #pragma omp parallel for num_threads(nthrds) \ private(i, j, k, sc) \ schedule(dynamic) for (i = 0; i < nrl; ++i) { if (bad_prime == 0) { int64_t *drl = dr + (omp_get_thread_num() * ncols); hm_t *npiv = upivs[i]; cf8_t *cfs = tbr->cf_8[npiv[COEFFS]]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const len_t bi = npiv[BINDEX]; const len_t mh = npiv[MULT]; const hm_t * const ds = npiv + OFFSET; k = 0; memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); for (j = 0; j < os; ++j) { drl[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { drl[ds[j]] = (int64_t)cfs[j]; drl[ds[j+1]] = (int64_t)cfs[j+1]; drl[ds[j+2]] = (int64_t)cfs[j+2]; drl[ds[j+3]] = (int64_t)cfs[j+3]; } cfs = NULL; do { /* If we do normal form computations the first monomial in the polynomial might not be a known pivot, thus setting it to npiv[OFFSET] can lead to wrong results. */ sc = st->nf == 0 ? npiv[OFFSET] : 0; free(npiv); free(cfs); npiv = mat->tr[i] = reduce_dense_row_by_known_pivots_sparse_ff_8( drl, mat, bs, pivs, sc, i, mh, bi, st->trace_level == LEARN_TRACER, st->fc); if (st->nf > 0) { if (!npiv) { mat->tr[i] = NULL; break; } mat->tr[i] = npiv; cfs = mat->cf_8[npiv[COEFFS]]; break; } else { if (!npiv) { if (st->trace_level == APPLY_TRACER) { bad_prime = 1; } break; } /* normalize coefficient array * NOTE: this has to be done here, otherwise the reduction may * lead to wrong results in a parallel computation since other * threads might directly use the new pivot once it is synced. */ if (mat->cf_8[npiv[COEFFS]][0] != 1) { normalize_sparse_matrix_row_ff_8( mat->cf_8[npiv[COEFFS]], npiv[PRELOOP], npiv[LENGTH], st->fc); } k = __sync_bool_compare_and_swap(&pivs[npiv[OFFSET]], NULL, npiv); cfs = mat->cf_8[npiv[COEFFS]]; } } while (!k); } } if (bad_prime == 1) { for (i = 0; i < ncl+ncr; ++i) { free(pivs[i]); pivs[i] = NULL; } mat->np = 0; if (st->info_level > 0) { fprintf(stderr, "Zero reduction while applying tracer, bad prime.\n"); } return; } /* construct the trace */ if (st->trace_level == LEARN_TRACER && st->in_final_reduction_step == 0) { construct_trace(st->tr, mat); } /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { free(pivs[i]); pivs[i] = NULL; } len_t npivs = 0; /* number of new pivots */ if (st->nf == 0 && st->in_final_reduction_step == 0) { dr = realloc(dr, (unsigned long)ncols * sizeof(int64_t)); mat->tr = realloc(mat->tr, (unsigned long)ncr * sizeof(hm_t *)); /* interreduce new pivots */ cf8_t *cfs; hm_t cf_array_pos; for (i = 0; i < ncr; ++i) { k = ncols-1-i; if (pivs[k]) { memset(dr, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = mat->cf_8[pivs[k][COEFFS]]; cf_array_pos = pivs[k][COEFFS]; const len_t os = pivs[k][PRELOOP]; const len_t len = pivs[k][LENGTH]; const len_t bi = pivs[k][BINDEX]; const len_t mh = pivs[k][MULT]; const hm_t * const ds = pivs[k] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { dr[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] = (int64_t)cfs[j]; dr[ds[j+1]] = (int64_t)cfs[j+1]; dr[ds[j+2]] = (int64_t)cfs[j+2]; dr[ds[j+3]] = (int64_t)cfs[j+3]; } free(pivs[k]); free(cfs); pivs[k] = NULL; pivs[k] = mat->tr[npivs++] = reduce_dense_row_by_known_pivots_sparse_ff_8( dr, mat, bs, pivs, sc, cf_array_pos, mh, bi, 0, st->fc); } } mat->tr = realloc(mat->tr, (unsigned long)npivs * sizeof(hi_t *)); st->np = mat->np = mat->nr = mat->sz = npivs; } else { st->np = mat->np = mat->nr = mat->sz = nrl; } free(pivs); pivs = NULL; free(dr); dr = NULL; } static cf8_t **sparse_AB_CD_linear_algebra_ff_8( mat_t *mat, const bs_t * bs, md_t *st ) { len_t i = 0, j; hi_t sc = 0; /* starting column */ const len_t ncols = mat->nc; const len_t nrl = mat->nrl; const len_t ncl = mat->ncl; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; /* dense rows representing updated D part; * after reducing CD part with AB */ cf8_t **drs = (cf8_t **)calloc((unsigned long)nrl, sizeof(cf8_t *)); int64_t *dr = (int64_t *)malloc( (unsigned long)(st->nthrds * ncols) * sizeof(int64_t)); /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ #pragma omp parallel for num_threads(st->nthrds) \ private(i, j, sc) \ schedule(dynamic) for (i = 0; i < nrl; ++i) { cf8_t *cfs = NULL; int64_t *drl = dr + (omp_get_thread_num() * ncols); hm_t *npiv = upivs[i]; /* do the reduction */ memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = bs->cf_8[npiv[COEFFS]]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const hm_t * const ds = npiv + OFFSET; for (j = 0; j < os; ++j) { drl[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { drl[ds[j]] = (int64_t)cfs[j]; drl[ds[j+1]] = (int64_t)cfs[j+1]; drl[ds[j+2]] = (int64_t)cfs[j+2]; drl[ds[j+3]] = (int64_t)cfs[j+3]; } sc = ds[0]; free(npiv); drs[i] = reduce_dense_row_by_old_pivots_ff_8( drl, mat, bs, pivs, sc, st->fc); } free(dr); dr = NULL; /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { free(pivs[i]); pivs[i] = NULL; } free(pivs); pivs = NULL; /* remove NULL dense rows */ len_t npivs = 0; /* number of new pivots */ for (i = 0; i < nrl; ++i) { if (drs[i] != NULL) { drs[npivs++] = drs[i]; } } if (npivs == 0) { free(drs); drs = NULL; } st->np = mat->np = npivs; return drs; } static cf8_t **interreduce_dense_matrix_ff_8( cf8_t **dm, const len_t ncr, const uint32_t fc ) { len_t i, j, k, l; int64_t *dr = malloc((unsigned long)ncr * sizeof(int64_t)); for (i = 0; i < ncr; ++i) { k = ncr-1-i; if (dm[k]) { memset(dr, 0, (unsigned long)ncr * sizeof(int64_t)); const len_t npc = ncr - k; const len_t os = npc % UNROLL; for (j = k, l = 0; l < os; ++j, ++l) { dr[j] = (int64_t)dm[k][l]; } for (; l < npc; j += UNROLL, l += UNROLL) { dr[j] = (int64_t)dm[k][l]; dr[j+1] = (int64_t)dm[k][l+1]; dr[j+2] = (int64_t)dm[k][l+2]; dr[j+3] = (int64_t)dm[k][l+3]; } free(dm[k]); dm[k] = NULL; /* start with previous pivot the reduction process, so keep the * pivot element as it is */ dm[k] = reduce_dense_row_by_dense_new_pivots_ff_8( dr, &k, dm, ncr, fc); } } free(dr); return dm; } static cf8_t **exact_dense_linear_algebra_ff_8( cf8_t **dm, mat_t *mat, md_t *st ) { len_t i, j, k, l, npivs; const len_t nrows = mat->np; /* we need the pivots until now here */ const len_t ncr = mat->ncr; /* rows already representing new pivots */ cf8_t **nps = (cf8_t **)calloc((unsigned long)ncr, sizeof(cf8_t *)); /* rows to be further reduced */ cf8_t **tbr = (cf8_t **)calloc((unsigned long)nrows, sizeof(cf8_t *)); int64_t *dr = (int64_t *)malloc( (unsigned long)(st->nthrds * ncr) * sizeof(int64_t)); /* separate rows already representing new pivots and rows to * be further reduced by these new pivots */ j = 0; npivs = 0; for (i = 0; i < nrows; ++i) { if (dm[i] != NULL) { k = 0; while (dm[i][k] == 0) { ++k; } if (nps[k] == NULL) { /* we have a pivot, cut the dense row down to start * at the first nonzero entry */ memmove(dm[i], dm[i]+k, (unsigned long)(ncr-k) * sizeof(cf8_t)); dm[i] = realloc(dm[i], (unsigned long)(ncr-k) * sizeof(cf8_t)); nps[k] = dm[i]; if (nps[k][0] != 1) { nps[k] = normalize_dense_matrix_row_ff_8(nps[k], ncr-k, st->fc); } } else { tbr[j++] = dm[i]; } } } free(dm); dm = NULL; const len_t ntr = j; tbr = realloc(tbr, (unsigned long)ntr * sizeof(cf8_t *)); /* offset modulo 4 for loop unrolling, +1 due to storing the first * nonzero entry at the first position */ /* reduction process to get all possible pivots, no interreduction here */ #pragma omp parallel for num_threads(st->nthrds) \ private(i, j, k, l) shared(nps, tbr) \ schedule(dynamic) for (i = 0; i < ntr; ++i) { int64_t *drl = dr + (omp_get_thread_num() * ncr); memset(drl, 0, (unsigned long)ncr * sizeof(int64_t)); hm_t npc = 0; hm_t os = 0; cf8_t *npiv = tbr[i]; os = (ncr-npc) % UNROLL; for (l = 0, j = npc; l < os; ++l, ++j) { drl[j] = (int64_t)npiv[l]; } for (; j < ncr; l += UNROLL, j += UNROLL) { drl[j] = (int64_t)npiv[l]; drl[j+1] = (int64_t)npiv[l+1]; drl[j+2] = (int64_t)npiv[l+2]; drl[j+3] = (int64_t)npiv[l+3]; } do { free(npiv); npiv = NULL; npiv = reduce_dense_row_by_dense_new_pivots_ff_8( drl, &npc, nps, mat->ncr, st->fc); if (npc == -1) { break; } k = __sync_bool_compare_and_swap(&nps[npc], NULL, npiv); /* some other thread has already added a pivot so we have to * recall the dense reduction process */ } while (!k); } /* count number of pivots */ const len_t os = ncr % UNROLL; for (i = 0; i < os; ++i) { if (nps[i] != NULL) { npivs++; } } for (; i < ncr; i += UNROLL) { if (nps[i] != NULL) { npivs++; } if (nps[i+1] != NULL) { npivs++; } if (nps[i+2] != NULL) { npivs++; } if (nps[i+3] != NULL) { npivs++; } } st->np = mat->np = npivs; free(tbr); free(dr); return nps; } static cf8_t **probabilistic_dense_linear_algebra_ff_8( cf8_t **dm, mat_t *mat, md_t *st ) { len_t i, j, k, l, m, npivs; const uint32_t fc = st->fc; const len_t nrows = mat->np; /* we need the pivots until now here */ const len_t ncols = mat->nc; const len_t ncr = mat->ncr; /* rows already representing new pivots */ cf8_t **nps = (cf8_t **)calloc((unsigned long)ncr, sizeof(cf8_t *)); /* rows to be further reduced */ cf8_t **tbr = (cf8_t **)calloc((unsigned long)nrows, sizeof(cf8_t *)); /* separate rows already representing new pivots and rows to * be further reduced by these new pivots */ j = 0; npivs = 0; for (i = 0; i < nrows; ++i) { if (dm[i] != NULL) { k = 0; while (dm[i][k] == 0) { ++k; } if (nps[k] == NULL) { /* we have a pivot, cut the dense row down to start * at the first nonzero entry */ memmove(dm[i], dm[i]+k, (unsigned long)(ncr-k) * sizeof(cf8_t)); dm[i] = realloc(dm[i], (unsigned long)(ncr-k) * sizeof(cf8_t)); nps[k] = dm[i]; if (nps[k][0] != 1) { nps[k] = normalize_dense_matrix_row_ff_8(nps[k], ncr-k, st->fc); } } else { tbr[j++] = dm[i]; } } } free(dm); dm = NULL; const len_t ntr = j; tbr = realloc(tbr, (unsigned long)ntr * sizeof(cf8_t *)); const int64_t mod2 = (int64_t)st->fc * st->fc; /* compute rows per block */ const len_t nb = (len_t)(floor(sqrt(ntr/3)))+1; const len_t rem = (ntr % nb == 0) ? 0 : 1; const len_t rpb = (ntr / nb) + rem; int64_t *dr = (int64_t *)malloc( (unsigned long)(st->nthrds * ncols) * sizeof(int64_t)); int64_t *mul = (int64_t *)malloc( (unsigned long)(st->nthrds * rpb) * sizeof(int64_t)); /* reduction process to get all possible pivots, no interreduction here */ #pragma omp parallel for num_threads(st->nthrds) \ private(i, j, k, l) shared(nps, tbr) \ schedule(dynamic) for (i = 0; i < ntr; ++i) { int64_t *drl = dr + (omp_get_thread_num() * ncr); int64_t *mull = mul + (omp_get_thread_num() * rpb); const int32_t nbl = (int32_t) (ntr > (i+1)*rpb ? (i+1)*rpb : ntr); const int32_t nrbl = (int32_t) (nbl - i*rpb); if (nrbl > 0) { hm_t npc; hm_t os; cf8_t *tmp; len_t bctr = 0; while (bctr < nrbl) { npc = 0; os = ncr % UNROLL; /* fill random value array */ for (j = 0; j < nrbl; ++j) { mull[j] = (int64_t)rand() % fc; } /* generate one dense row as random linear combination * of the rows of the block */ memset(drl, 0, (unsigned long)ncr * sizeof(int64_t)); for (k = 0, m = i*rpb; m < nbl; ++k, ++m) { tmp = tbr[m]; for (l = 0, j = npc; l < os; ++l, ++j) { drl[j] -= mull[k] * tmp[l]; drl[j] += (drl[j] >> 63) & mod2; } for (; j < ncr; l += UNROLL, j += UNROLL) { drl[j] -= mull[k] * tmp[l]; drl[j] += (drl[j] >> 63) & mod2; drl[j+1] -= mull[k] * tmp[l+1]; drl[j+1] += (drl[j+1] >> 63) & mod2; drl[j+2] -= mull[k] * tmp[l+2]; drl[j+2] += (drl[j+2] >> 63) & mod2; drl[j+3] -= mull[k] * tmp[l+3]; drl[j+3] += (drl[j+3] >> 63) & mod2; } } k = 0; npc = 0; /* do the reduction */ tmp = NULL; do { free(tmp); tmp = reduce_dense_row_by_dense_new_pivots_ff_8( drl, &npc, nps, mat->ncr, st->fc); if (npc == -1) { bctr = nrbl; break; } k = __sync_bool_compare_and_swap(&nps[npc], NULL, tmp); /* some other thread has already added a pivot so we have to * recall the dense reduction process */ } while (!k); bctr++; } for (j = i*rpb; j < nbl; ++j) { free(tbr[j]); tbr[j] = NULL; } } } /* count number of pivots */ const len_t os = ncr % UNROLL; for (i = 0; i < os; ++i) { if (nps[i] != NULL) { npivs++; } } for (; i < ncr; i += UNROLL) { if (nps[i] != NULL) { npivs++; } if (nps[i+1] != NULL) { npivs++; } if (nps[i+2] != NULL) { npivs++; } if (nps[i+3] != NULL) { npivs++; } } st->np = mat->np = npivs; free(mul); free(tbr); free(dr); return nps; } static cf8_t **probabilistic_sparse_dense_echelon_form_ff_8( mat_t *mat, const bs_t * const bs, md_t *st ) { len_t i = 0, j, k, l, m, npivs; const len_t nru = mat->nru; const len_t nrl = mat->nrl; const len_t ncr = mat->ncr; const len_t ncols = mat->nc; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; /* rows already representing new pivots */ cf8_t **nps = (cf8_t **)calloc((unsigned long)ncr, sizeof(cf8_t *)); const uint32_t fc = st->fc; const int64_t mod2 = (int64_t)fc * fc; /* compute rows per block */ const len_t nb = (len_t)(floor(sqrt(nrl/3)))+1; const len_t rem = (nrl % nb == 0) ? 0 : 1; const len_t rpb = (nrl / nb) + rem; int64_t *dr = (int64_t *)malloc( (unsigned long)(st->nthrds * ncols) * sizeof(int64_t)); int64_t *mul = (int64_t *)malloc( (unsigned long)(st->nthrds * rpb) * sizeof(int64_t)); /* reduction process to get all possible pivots, no interreduction here */ #pragma omp parallel for num_threads(st->nthrds) \ private(i, j, k, l, m) shared(nps) \ schedule(dynamic) for (i = 0; i < nb; ++i) { int64_t *drl = dr + (omp_get_thread_num() * ncols); int64_t *mull = mul + (omp_get_thread_num() * rpb); const int32_t nbl = (int32_t) (nrl > (i+1)*rpb ? (i+1)*rpb : nrl); const int32_t nrbl = (int32_t) (nbl - i*rpb); if (nrbl > 0) { hm_t *npiv; cf8_t *tmp; hm_t npc; len_t bctr = 0; while (bctr < nrbl) { npc = 0; /* fill random value array */ for (j = 0; j < nrbl; ++j) { mull[j] = (int64_t)rand() % fc; } /* generate one dense row as random linear combination * of the rows of the block */ memset(drl, 0, (unsigned long)ncols * sizeof(int64_t)); for (k = 0, m = i*rpb; m < nbl; ++k, ++m) { npiv = upivs[m]; tmp = bs->cf_8[npiv[COEFFS]]; const len_t os = npiv[PRELOOP]; const len_t len = npiv[LENGTH]; const hm_t * const ds = npiv + OFFSET; for (l = 0; l < os; ++l) { drl[ds[l]] -= mull[k] * tmp[l]; drl[ds[l]] += (drl[ds[l]] >> 63) & mod2; } for (; l < len; l += UNROLL) { drl[ds[l]] -= mull[k] * tmp[l]; drl[ds[l]] += (drl[ds[l]] >> 63) & mod2; drl[ds[l+1]] -= mull[k] * tmp[l+1]; drl[ds[l+1]] += (drl[ds[l+1]] >> 63) & mod2; drl[ds[l+2]] -= mull[k] * tmp[l+2]; drl[ds[l+2]] += (drl[ds[l+2]] >> 63) & mod2; drl[ds[l+3]] -= mull[k] * tmp[l+3]; drl[ds[l+3]] += (drl[ds[l+3]] >> 63) & mod2; } } k = 0; npc = 0; /* do the reduction */ tmp = NULL; do { free(tmp); tmp = reduce_dense_row_by_all_pivots_ff_8( drl, mat, bs, &npc, pivs, nps, st->fc); if (npc == -1) { bctr = nrbl; break; } k = __sync_bool_compare_and_swap(&nps[npc], NULL, tmp); /* some other thread has already added a pivot so we have to * recall the dense reduction process */ } while (!k); bctr++; } for (j = i*rpb; j < nbl; ++j) { free(upivs[j]); upivs[j] = NULL; } } } npivs = 0; /* count number of pivots */ const len_t os = ncr % UNROLL; for (i = 0; i < os; ++i) { if (nps[i] != NULL) { npivs++; } } for (; i < ncr; i += UNROLL) { if (nps[i] != NULL) { npivs++; } if (nps[i+1] != NULL) { npivs++; } if (nps[i+2] != NULL) { npivs++; } if (nps[i+3] != NULL) { npivs++; } } st->np = mat->np = npivs; for (i = 0; i < nru; ++i) { free(pivs[i]); } free(pivs); pivs = NULL; free(mul); mul = NULL; free(dr); dr = NULL; return nps; } static void convert_to_sparse_matrix_rows_ff_8( mat_t *mat, cf8_t * const * const dm ) { if (mat->np == 0) { return; } len_t i, j, k, l, m; cf8_t *cfs; hm_t *dts, *dss; const len_t ncr = mat->ncr; const len_t ncl = mat->ncl; mat->tr = realloc(mat->tr, (unsigned long)mat->np * sizeof(hm_t *)); mat->cf_8 = realloc(mat->cf_8, (unsigned long)mat->np * sizeof(cf8_t *)); l = 0; for (i = 0; i < ncr; ++i) { m = ncr-1-i; if (dm[m] != NULL) { cfs = malloc((unsigned long)(ncr-m) * sizeof(cf8_t)); dts = malloc((unsigned long)(ncr-m+OFFSET) * sizeof(hm_t)); const hm_t len = ncr-m; const hm_t os = len % UNROLL; const hm_t shift = ncl+m; dss = dts + OFFSET; for (k = 0, j = 0; j < os; ++j) { if (dm[m][j] != 0) { cfs[k] = dm[m][j]; dss[k++] = j+shift; } } for (; j < len; j += UNROLL) { if (dm[m][j] != 0) { cfs[k] = dm[m][j]; dss[k++] = j+shift; } if (dm[m][j+1] != 0) { cfs[k] = dm[m][j+1]; dss[k++] = j+1+shift; } if (dm[m][j+2] != 0) { cfs[k] = dm[m][j+2]; dss[k++] = j+2+shift; } if (dm[m][j+3] != 0) { cfs[k] = dm[m][j+3]; dss[k++] = j+3+shift; } } /* store meta data in first entries */ dts[COEFFS] = l; /* position of coefficient array in tmpcf */ dts[PRELOOP] = k % UNROLL; dts[LENGTH] = k; /* adjust memory usage */ dts = realloc(dts, (unsigned long)(k+OFFSET) * sizeof(hm_t)); cfs = realloc(cfs, (unsigned long)k * sizeof(cf8_t)); /* link to basis */ mat->tr[l] = dts; mat->cf_8[l] = cfs; l++; } } } /* NOTE: this note is about the different linear algebra implementations: * exact and probabilistic linear algebra differ only in the last, * dense reduction step: the reduction of CD via AB is sparse and * the same for both. this generates a dense D' part which is then * either reduced via exact linear algebra or via probabilistic * linear algebra */ static void probabilistic_sparse_linear_algebra_ff_8( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* allocate temporary storage space for sparse * coefficients of all pivot rows */ mat->cf_8 = realloc(mat->cf_8, (unsigned long)mat->nr * sizeof(cf8_t *)); probabilistic_sparse_reduced_echelon_form_ff_8(mat, bs, st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static int exact_application_sparse_linear_algebra_ff_8( mat_t *mat, const bs_t * const bs, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); int ret; /* allocate temporary storage space for sparse * coefficients of all pivot rows */ mat->cf_8 = realloc(mat->cf_8, (unsigned long)mat->nr * sizeof(cf8_t *)); ret = exact_application_sparse_reduced_echelon_form_ff_8(mat, bs, st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } return ret; } static void exact_trace_sparse_linear_algebra_ff_8( trace_t *trace, mat_t *mat, const bs_t * const bs, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* allocate temporary storage space for sparse * coefficients of all pivot rows */ mat->cf_8 = realloc(mat->cf_8, (unsigned long)mat->nr * sizeof(cf8_t *)); exact_trace_sparse_reduced_echelon_form_ff_8(trace, mat, bs, st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static void exact_sparse_linear_algebra_ff_8( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* allocate temporary storage space for sparse * coefficients of all pivot rows */ mat->cf_8 = realloc(mat->cf_8, (unsigned long)mat->nr * sizeof(cf8_t *)); exact_sparse_reduced_echelon_form_ff_8(mat, tbr, bs, st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static void exact_sparse_dense_linear_algebra_ff_8( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { len_t i; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); const len_t ncr = mat->ncr; /* generate updated dense D part via reduction of CD with AB */ cf8_t **dm; dm = sparse_AB_CD_linear_algebra_ff_8(mat, bs, st); if (mat->np > 0) { dm = exact_dense_linear_algebra_ff_8(dm, mat, st); dm = interreduce_dense_matrix_ff_8(dm, ncr, st->fc); } /* convert dense matrix back to sparse matrix representation, * use tmpcf for storing the coefficient arrays */ convert_to_sparse_matrix_rows_ff_8(mat, dm); /* free dm */ if (dm) { for (i = 0; i < ncr; ++i) { free(dm[i]); } free(dm); dm = NULL; } /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static void probabilistic_sparse_dense_linear_algebra_ff_8_2( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { len_t i; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); const len_t ncr = mat->ncr; /* generate updated dense D part via reduction of CD with AB */ cf8_t **dm; dm = sparse_AB_CD_linear_algebra_ff_8(mat, bs, st); if (mat->np > 0) { dm = probabilistic_dense_linear_algebra_ff_8(dm, mat, st); dm = interreduce_dense_matrix_ff_8(dm, mat->ncr, st->fc); } /* convert dense matrix back to sparse matrix representation, * use tmpcf for storing the coefficient arrays */ convert_to_sparse_matrix_rows_ff_8(mat, dm); /* free dm */ if (dm) { for (i = 0; i < ncr; ++i) { free(dm[i]); } free(dm); dm = NULL; } /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static void probabilistic_sparse_dense_linear_algebra_ff_8( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { len_t i; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); const len_t ncr = mat->ncr; /* generate updated dense D part via reduction of CD with AB */ cf8_t **dm = NULL; mat->np = 0; dm = probabilistic_sparse_dense_echelon_form_ff_8(mat, bs, st); dm = interreduce_dense_matrix_ff_8(dm, mat->ncr, st->fc); /* convert dense matrix back to sparse matrix representation, * use tmpcf for storing the coefficient arrays */ convert_to_sparse_matrix_rows_ff_8(mat, dm); /* free dm */ if (dm) { for (i = 0; i < ncr; ++i) { free(dm[i]); } free(dm); dm = NULL; } /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%9d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static void interreduce_matrix_rows_ff_8( mat_t *mat, bs_t *bs, md_t *st, int free_basis ) { len_t i, j, k, l; const len_t nrows = mat->nr; const len_t ncols = mat->nc; /* adjust displaying timings for statistic printout */ if (st->info_level > 1) { printf(" "); } /* for interreduction steps like the final basis reduction we need to allocate memory for rba here, even so we do not use it at all */ mat->rba = (rba_t **)malloc((unsigned long)ncols * sizeof(rba_t *)); const unsigned long len = ncols / 32 + ((ncols % 32) != 0); for (i = 0; i < ncols; ++i) { mat->rba[i] = (rba_t *)calloc(len, sizeof(rba_t)); } mat->tr = realloc(mat->tr, (unsigned long)ncols * sizeof(hm_t *)); mat->cf_8 = realloc(mat->cf_8, (unsigned long)ncols * sizeof(cf32_t *)); memset(mat->cf_8, 0, (unsigned long)ncols * sizeof(cf8_t *)); hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); /* copy coefficient arrays from basis in matrix, maybe * several rows need the same coefficient arrays, but we * cannot share them here. */ for (i = 0; i < nrows; ++i) { pivs[mat->rr[i][OFFSET]] = mat->rr[i]; } int64_t *dr = (int64_t *)malloc((unsigned long)ncols * sizeof(int64_t)); /* interreduce new pivots */ cf8_t *cfs; /* starting column, coefficient array position in tmpcf */ hm_t sc; k = nrows - 1; for (i = 0; i < ncols; ++i) { l = ncols-1-i; if (pivs[l] != NULL) { memset(dr, 0, (unsigned long)ncols * sizeof(int64_t)); cfs = bs->cf_8[pivs[l][COEFFS]]; const len_t bi = pivs[l][BINDEX]; const len_t mh = pivs[l][MULT]; const len_t os = pivs[l][PRELOOP]; const len_t len = pivs[l][LENGTH]; const hm_t * const ds = pivs[l] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { dr[ds[j]] = (int64_t)cfs[j]; } for (; j < len; j += UNROLL) { dr[ds[j]] = (int64_t)cfs[j]; dr[ds[j+1]] = (int64_t)cfs[j+1]; dr[ds[j+2]] = (int64_t)cfs[j+2]; dr[ds[j+3]] = (int64_t)cfs[j+3]; } free(pivs[l]); pivs[l] = NULL; pivs[l] = mat->tr[k--] = reduce_dense_row_by_known_pivots_sparse_ff_8( dr, mat, bs, pivs, sc, l, mh, bi, 0, st->fc); } } for (i = 0; i < ncols; ++i) { free(mat->rba[i]); mat->rba[i] = NULL; } if (free_basis != 0) { /* free now all polynomials in the basis and reset bs->ld to 0. */ free_basis_elements(bs); } free(mat->rr); mat->rr = NULL; st->np = mat->np = nrows; free(pivs); free(dr); } msolve-0.6.5/src/neogb/la_qq.c000066400000000000000000000703721456710632100161670ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "data.h" static inline mpz_t *remove_content_of_sparse_matrix_row_qq( mpz_t *row, const len_t os, const len_t len ) { len_t i; long remove = 1; mpz_t content; /* compute content, i.e. gcd of all coefficients */ mpz_init_set(content, row[0]); for (i = 1; i < len; ++i) { mpz_gcd(content, content, row[i]); if (mpz_cmp_si(content, 1) == 0) { remove = 0; break; } } if (remove == 1) { /* remove content */ for (i = 0; i < os; ++i) { mpz_divexact(row[i], row[i], content); } for (; i < len; i += UNROLL) { mpz_divexact(row[i], row[i], content); mpz_divexact(row[i+1], row[i+1], content); mpz_divexact(row[i+2], row[i+2], content); mpz_divexact(row[i+3], row[i+3], content); } } mpz_clear(content); /* make lead coefficient positive */ if (mpz_sgn(row[0]) < 0) { for (i = 0; i < os; ++i) { mpz_neg(row[i], row[i]); } for (; i < len; i += UNROLL) { mpz_neg(row[i], row[i]); mpz_neg(row[i+1], row[i+1]); mpz_neg(row[i+2], row[i+2]); mpz_neg(row[i+3], row[i+3]); } } return row; } static hm_t *reduce_dense_row_by_known_pivots_sparse_only_ab_qq( mpz_t *dr, mat_t *mat, hm_t * const * const pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const hm_t tmp_pos /* position of new coeffs array in tmpcf */ ) { hi_t i, j; hm_t *dts; mpz_t *cfs; int64_t np = -1; const len_t ncols = mat->nc; const len_t ncl = mat->ncl; hm_t *row = NULL; mpz_t *cf = NULL; len_t rlen = 0; mpz_t mul1, mul2; mpz_inits(mul1, mul2, NULL); for (i = dpiv; i < ncl; ++i) { /* uses mpz_sgn for checking if dr[i] = 0 */ if (mpz_sgn(dr[i]) == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { row = (hm_t *)malloc( (unsigned long)(ncols-i+OFFSET) * sizeof(hm_t)); cf = (mpz_t *)malloc( (unsigned long)(ncols-i) * sizeof(mpz_t)); np = i; } mpz_init(cf[rlen]); mpz_swap(cf[rlen], dr[i]); row[rlen+OFFSET] = i; rlen++; continue; } /* found reducer row, get multiplier */ dts = pivs[i]; cfs = mat->cf_ab_qq[dts[COEFFS]]; const len_t os = dts[PRELOOP]; const len_t len = dts[LENGTH]; const hm_t * const ds = dts + OFFSET; /* check if lead coefficient of dr is multiple of lead coefficient * of cfs, generate corresponding multipliers respectively */ if (mpz_divisible_p(dr[i], cfs[0]) != 0) { mpz_divexact(mul2, dr[i], cfs[0]); } else { mpz_lcm(mul1, dr[i], cfs[0]); mpz_divexact(mul2, mul1, cfs[0]); mpz_divexact(mul1, mul1, dr[i]); for (j = 0; j < rlen; ++j) { mpz_mul(cf[j], cf[j], mul1); } for (j = i+1; j < ncols; ++j) { if (mpz_sgn(dr[j]) != 0) { mpz_mul(dr[j], dr[j], mul1); } } } for (j = 0; j < os; ++j) { mpz_submul(dr[ds[j]], mul2, cfs[j]); } for (; j < len; j += UNROLL) { mpz_submul(dr[ds[j]], mul2, cfs[j]); mpz_submul(dr[ds[j+1]], mul2, cfs[j+1]); mpz_submul(dr[ds[j+2]], mul2, cfs[j+2]); mpz_submul(dr[ds[j+3]], mul2, cfs[j+3]); } } if (rlen != 0) { for (i = ncl; i < ncols; ++i) { if (mpz_sgn(dr[i]) == 0) { continue; } mpz_init(cf[rlen]); mpz_swap(cf[rlen], dr[i]); row[rlen+OFFSET] = i; rlen++; } row = realloc(row, (unsigned long)(rlen+OFFSET) * sizeof(hm_t)); cf = realloc(cf, (unsigned long)rlen * sizeof(mpz_t)); row[COEFFS] = tmp_pos; row[PRELOOP] = rlen % UNROLL; row[LENGTH] = rlen; mat->cf_ab_qq[tmp_pos] = cf; } mpz_clears(mul1, mul2, NULL); return row; } static hm_t *reduce_dense_row_by_known_pivots_sparse_ab_first_qq( mpz_t *dr, mat_t *mat, hm_t * const * const pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const hm_t tmp_pos /* position of new coeffs array in tmpcf */ ) { hi_t i, j; hm_t *dts; mpz_t *cfs; int64_t np = -1; const len_t ncols = mat->nc; const len_t ncl = mat->ncl; mpz_t * const * const mcf = mat->cf_qq; hm_t *row = NULL; mpz_t *cf = NULL; len_t rlen = 0; mpz_t mul1, mul2; mpz_inits(mul1, mul2, NULL); for (i = dpiv; i < ncols; ++i) { /* uses mpz_sgn for checking if dr[i] = 0 */ if (mpz_sgn(dr[i]) == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { row = (hm_t *)malloc( (unsigned long)(ncols-i+OFFSET) * sizeof(hm_t)); cf = (mpz_t *)malloc( (unsigned long)(ncols-i) * sizeof(mpz_t)); np = i; } mpz_init(cf[rlen]); mpz_swap(cf[rlen], dr[i]); row[rlen+OFFSET] = i; rlen++; continue; } /* found reducer row, get multiplier */ dts = pivs[i]; if (i < ncl) { cfs = mat->cf_ab_qq[dts[COEFFS]]; } else { cfs = mcf[dts[COEFFS]]; } const len_t os = dts[PRELOOP]; const len_t len = dts[LENGTH]; const hm_t * const ds = dts + OFFSET; /* check if lead coefficient of dr is multiple of lead coefficient * of cfs, generate corresponding multipliers respectively */ if (mpz_divisible_p(dr[i], cfs[0]) != 0) { mpz_divexact(mul2, dr[i], cfs[0]); } else { mpz_lcm(mul1, dr[i], cfs[0]); mpz_divexact(mul2, mul1, cfs[0]); mpz_divexact(mul1, mul1, dr[i]); for (j = 0; j < rlen; ++j) { mpz_mul(cf[j], cf[j], mul1); } for (j = i+1; j < ncols; ++j) { if (mpz_sgn(dr[j]) != 0) { mpz_mul(dr[j], dr[j], mul1); } } } for (j = 0; j < os; ++j) { mpz_submul(dr[ds[j]], mul2, cfs[j]); } for (; j < len; j += UNROLL) { mpz_submul(dr[ds[j]], mul2, cfs[j]); mpz_submul(dr[ds[j+1]], mul2, cfs[j+1]); mpz_submul(dr[ds[j+2]], mul2, cfs[j+2]); mpz_submul(dr[ds[j+3]], mul2, cfs[j+3]); } } if (rlen != 0) { row = realloc(row, (unsigned long)(rlen+OFFSET) * sizeof(hm_t)); cf = realloc(cf, (unsigned long)rlen * sizeof(mpz_t)); row[COEFFS] = tmp_pos; row[PRELOOP] = rlen % UNROLL; row[LENGTH] = rlen; mat->cf_qq[tmp_pos] = cf; } mpz_clears(mul1, mul2, NULL); return row; } static hm_t *reduce_dense_row_by_known_pivots_sparse_qq( mpz_t *dr, mat_t *mat, const bs_t * const bs, hm_t * const * const pivs, const hi_t dpiv, /* pivot of dense row at the beginning */ const hm_t tmp_pos /* position of new coeffs array in tmpcf */ ) { hi_t i, j; hm_t *dts; mpz_t *cfs; int64_t np = -1; const len_t ncols = mat->nc; const len_t ncl = mat->ncl; mpz_t * const * const mcf = mat->cf_qq; hm_t *row = NULL; mpz_t *cf = NULL; len_t rlen = 0; mpz_t mul1, mul2; mpz_inits(mul1, mul2, NULL); for (i = dpiv; i < ncols; ++i) { /* uses mpz_sgn for checking if dr[i] = 0 */ if (mpz_sgn(dr[i]) == 0) { continue; } if (pivs[i] == NULL) { if (np == -1) { row = (hm_t *)malloc( (unsigned long)(ncols-i+OFFSET) * sizeof(hm_t)); cf = (mpz_t *)malloc( (unsigned long)(ncols-i) * sizeof(mpz_t)); np = i; } mpz_init(cf[rlen]); mpz_swap(cf[rlen], dr[i]); row[rlen+OFFSET] = i; rlen++; continue; } /* found reducer row, get multiplier */ dts = pivs[i]; if (i < ncl) { cfs = bs->cf_qq[dts[COEFFS]]; } else { cfs = mcf[dts[COEFFS]]; } const len_t os = dts[PRELOOP]; const len_t len = dts[LENGTH]; const hm_t * const ds = dts + OFFSET; /* check if lead coefficient of dr is multiple of lead coefficient * of cfs, generate corresponding multipliers respectively */ if (mpz_divisible_p(dr[i], cfs[0]) != 0) { mpz_divexact(mul2, dr[i], cfs[0]); } else { mpz_lcm(mul1, dr[i], cfs[0]); mpz_divexact(mul2, mul1, cfs[0]); mpz_divexact(mul1, mul1, dr[i]); for (j = 0; j < rlen; ++j) { mpz_mul(cf[j], cf[j], mul1); } for (j = i+1; j < ncols; ++j) { if (mpz_sgn(dr[j]) != 0) { mpz_mul(dr[j], dr[j], mul1); } } } for (j = 0; j < os; ++j) { mpz_submul(dr[ds[j]], mul2, cfs[j]); } for (; j < len; j += UNROLL) { mpz_submul(dr[ds[j]], mul2, cfs[j]); mpz_submul(dr[ds[j+1]], mul2, cfs[j+1]); mpz_submul(dr[ds[j+2]], mul2, cfs[j+2]); mpz_submul(dr[ds[j+3]], mul2, cfs[j+3]); } } if (rlen != 0) { row = realloc(row, (unsigned long)(rlen+OFFSET) * sizeof(hm_t)); cf = realloc(cf, (unsigned long)rlen * sizeof(mpz_t)); row[COEFFS] = tmp_pos; row[PRELOOP] = rlen % UNROLL; row[LENGTH] = rlen; mat->cf_qq[tmp_pos] = cf; } mpz_clears(mul1, mul2, NULL); return row; } static void exact_sparse_reduced_echelon_form_ab_first_qq( mat_t *mat, const bs_t * const bs, const md_t * const st ) { len_t i = 0, j, k; hi_t sc = 0; /* starting column */ const len_t ncols = mat->nc; const len_t nru = mat->nru; const len_t nrl = mat->nrl; const len_t ncr = mat->ncr; const len_t ncl = mat->ncl; mpz_t *cfs; hm_t cf_array_pos; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; mpz_t *dr = (mpz_t *)malloc( (unsigned long)ncols * sizeof(mpz_t)); for (i = 0; i < ncols; ++i) { mpz_init(dr[i]); } mat->cf_ab_qq[nru-1] = (mpz_t *)malloc( (unsigned long)pivs[nru-1][LENGTH] * sizeof(mpz_t)); for (i = 0 ; i < pivs[nru-1][LENGTH]; ++i) { mpz_init_set(mat->cf_ab_qq[nru-1][i], bs->cf_qq[pivs[nru-1][COEFFS]][i]); } pivs[nru-1][COEFFS] = nru-1; for (i = 0; i < nru-1; ++i) { k = nru-2-i; for (j = 0; j < ncols; ++j) { mpz_set_si(dr[j], 0); } cfs = bs->cf_qq[pivs[k][COEFFS]]; const len_t os = pivs[k][PRELOOP]; const len_t len = pivs[k][LENGTH]; const hm_t * const ds = pivs[k] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { mpz_set(dr[ds[j]], cfs[j]); } for (; j < len; j += UNROLL) { mpz_set(dr[ds[j]], cfs[j]); mpz_set(dr[ds[j+1]], cfs[j+1]); mpz_set(dr[ds[j+2]], cfs[j+2]); mpz_set(dr[ds[j+3]], cfs[j+3]); } free(pivs[k]); cfs = NULL;; pivs[k] = NULL; pivs[k] = reduce_dense_row_by_known_pivots_sparse_only_ab_qq( dr, mat, pivs, sc, k); remove_content_of_sparse_matrix_row_qq( mat->cf_ab_qq[pivs[k][COEFFS]], pivs[k][PRELOOP], pivs[k][LENGTH]); } const len_t drlen = st->nthrds * ncols; dr = realloc(dr, (unsigned long)drlen * sizeof(mpz_t)); for (i = ncols; i < drlen; ++i) { mpz_init(dr[i]); } /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ #pragma omp parallel for num_threads(st->nthrds) private(i, j, k, sc) schedule(dynamic) for (i = 0; i < nrl; ++i) { mpz_t *drl = dr + (omp_get_thread_num() * ncols); hm_t *npiv = upivs[i]; mpz_t *cfs = bs->cf_qq[npiv[COEFFS]]; len_t os = npiv[PRELOOP]; len_t len = npiv[LENGTH]; hm_t * ds = npiv + OFFSET; k = 0; /* reset entries to zero */ for (j = 0; j < ncols; ++j) { mpz_set_si(drl[j], 0); } for (j = 0; j < os; ++j) { mpz_set(drl[ds[j]], cfs[j]); } for (; j < len; j += UNROLL) { mpz_set(drl[ds[j]], cfs[j]); mpz_set(drl[ds[j+1]], cfs[j+1]); mpz_set(drl[ds[j+2]], cfs[j+2]); mpz_set(drl[ds[j+3]], cfs[j+3]); } cfs = NULL; k = 1; do { sc = npiv[OFFSET]; os = npiv[PRELOOP]; len = npiv[LENGTH]; ds = npiv + OFFSET; if (k == 0) { /* if we redo the row than we only handle elements * with column index >= sc, so we do not need to * reset the other entries in the row to zero */ for (j = sc; j < ncols; ++j) { mpz_set_si(drl[j], 0); } for (j = 0; j < os; ++j) { mpz_swap(drl[ds[j]], cfs[j]); mpz_clear(cfs[j]); } for (; j < len; j += UNROLL) { mpz_swap(drl[ds[j]], cfs[j]); mpz_clear(cfs[j]); mpz_swap(drl[ds[j+1]], cfs[j+1]); mpz_clear(cfs[j+1]); mpz_swap(drl[ds[j+2]], cfs[j+2]); mpz_clear(cfs[j+2]); mpz_swap(drl[ds[j+3]], cfs[j+3]); mpz_clear(cfs[j+3]); } } free(cfs); free(npiv); npiv = reduce_dense_row_by_known_pivots_sparse_ab_first_qq( drl, mat, pivs, sc, i); if (!npiv) { break; } /* remove content of coefficient array for better usage as reducer * later on. * NOTE: this has to be done here, otherwise the reduction may * lead to wrong results in a parallel computation since other * threads might directly use the new pivot once it is synced. */ if (mpz_cmp_si(mat->cf_qq[npiv[COEFFS]][0], 1) != 0) { remove_content_of_sparse_matrix_row_qq( mat->cf_qq[npiv[COEFFS]], npiv[PRELOOP], npiv[LENGTH]); } k = __sync_bool_compare_and_swap(&pivs[npiv[OFFSET]], NULL, npiv); cfs = mat->cf_qq[npiv[COEFFS]]; } while (k == 0); cfs = NULL; } /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { for (j = 0; j < pivs[i][LENGTH]; ++j) { mpz_clear(mat->cf_ab_qq[pivs[i][COEFFS]][j]); } free(mat->cf_ab_qq[pivs[i][COEFFS]]); mat->cf_ab_qq[pivs[i][COEFFS]] = NULL; free(pivs[i]); pivs[i] = NULL; } len_t npivs = 0; /* number of new pivots */ for (i = ncols; i < drlen; ++i) { mpz_clear(dr[i]); } dr = realloc(dr, (unsigned long)ncols * sizeof(mpz_t)); mat->tr = realloc(mat->tr, (unsigned long)ncr * sizeof(hm_t *)); /* interreduce new pivots */ for (i = 0; i < ncr; ++i) { k = ncols-1-i; if (pivs[k]) { for (j = 0; j < ncols; ++j) { mpz_set_si(dr[j], 0); } cfs = mat->cf_qq[pivs[k][COEFFS]]; cf_array_pos = pivs[k][COEFFS]; const len_t os = pivs[k][PRELOOP]; const len_t len = pivs[k][LENGTH]; const hm_t * const ds = pivs[k] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { mpz_swap(dr[ds[j]], cfs[j]); mpz_clear(cfs[j]); } for (; j < len; j += UNROLL) { mpz_swap(dr[ds[j]], cfs[j]); mpz_clear(cfs[j]); mpz_swap(dr[ds[j+1]], cfs[j+1]); mpz_clear(cfs[j+1]); mpz_swap(dr[ds[j+2]], cfs[j+2]); mpz_clear(cfs[j+2]); mpz_swap(dr[ds[j+3]], cfs[j+3]); mpz_clear(cfs[j+3]); } free(pivs[k]); free(cfs); pivs[k] = NULL; pivs[k] = mat->tr[npivs] = reduce_dense_row_by_known_pivots_sparse_qq( dr, mat, bs, pivs, sc, cf_array_pos); remove_content_of_sparse_matrix_row_qq( mat->cf_qq[mat->tr[npivs][COEFFS]], mat->tr[npivs][PRELOOP], mat->tr[npivs][LENGTH]); npivs++; } } free(pivs); pivs = NULL; for (i = 0; i < ncols; ++i) { mpz_clear(dr[i]); } free(dr); dr = NULL; mat->tr = realloc(mat->tr, (unsigned long)npivs * sizeof(hi_t *)); mat->np = mat->nr = mat->sz = npivs; } static void exact_sparse_reduced_echelon_form_qq( mat_t *mat, const bs_t * const bs, const md_t * const st ) { len_t i = 0, j, k; hi_t sc = 0; /* starting column */ const len_t ncols = mat->nc; const len_t nrl = mat->nrl; const len_t ncr = mat->ncr; const len_t ncl = mat->ncl; /* we fill in all known lead terms in pivs */ hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); memcpy(pivs, mat->rr, (unsigned long)mat->nru * sizeof(hm_t *)); /* unkown pivot rows we have to reduce with the known pivots first */ hm_t **upivs = mat->tr; const len_t drlen = st->nthrds * ncols; mpz_t *dr = (mpz_t *)malloc( (unsigned long)drlen * sizeof(mpz_t)); for (i = 0; i < drlen; ++i) { mpz_init(dr[i]); } /* mo need to have any sharing dependencies on parallel computation, * no data to be synchronized at this step of the linear algebra */ #pragma omp parallel for num_threads(st->nthrds) private(i, j, k, sc) \ schedule(dynamic) for (i = 0; i < nrl; ++i) { mpz_t *drl = dr + (omp_get_thread_num() * ncols); hm_t *npiv = upivs[i]; mpz_t *cfs = bs->cf_qq[npiv[COEFFS]]; len_t os = npiv[PRELOOP]; len_t len = npiv[LENGTH]; hm_t * ds = npiv + OFFSET; k = 0; /* reset entries to zero */ for (j = 0; j < ncols; ++j) { mpz_set_si(drl[j], 0); } for (j = 0; j < os; ++j) { mpz_set(drl[ds[j]], cfs[j]); } for (; j < len; j += UNROLL) { mpz_set(drl[ds[j]], cfs[j]); mpz_set(drl[ds[j+1]], cfs[j+1]); mpz_set(drl[ds[j+2]], cfs[j+2]); mpz_set(drl[ds[j+3]], cfs[j+3]); } cfs = NULL; k = 1; do { sc = npiv[OFFSET]; os = npiv[PRELOOP]; len = npiv[LENGTH]; ds = npiv + OFFSET; if (k == 0) { /* if we redo the row than we only handle elements * with column index >= sc, so we do not need to * reset the other entries in the row to zero */ for (j = sc; j < ncols; ++j) { mpz_set_si(drl[j], 0); } for (j = 0; j < os; ++j) { mpz_swap(drl[ds[j]], cfs[j]); mpz_clear(cfs[j]); } for (; j < len; j += UNROLL) { mpz_swap(drl[ds[j]], cfs[j]); mpz_clear(cfs[j]); mpz_swap(drl[ds[j+1]], cfs[j+1]); mpz_clear(cfs[j+1]); mpz_swap(drl[ds[j+2]], cfs[j+2]); mpz_clear(cfs[j+2]); mpz_swap(drl[ds[j+3]], cfs[j+3]); mpz_clear(cfs[j+3]); } } free(cfs); free(npiv); npiv = reduce_dense_row_by_known_pivots_sparse_qq( drl, mat, bs, pivs, sc, i); if (!npiv) { break; } /* remove content of coefficient array for better usage as reducer * later on. * NOTE: this has to be done here, otherwise the reduction may * lead to wrong results in a parallel computation since other * threads might directly use the new pivot once it is synced. */ if (mpz_cmp_si(mat->cf_qq[npiv[COEFFS]][0], 1) != 0) { remove_content_of_sparse_matrix_row_qq( mat->cf_qq[npiv[COEFFS]], npiv[PRELOOP], npiv[LENGTH]); } k = __sync_bool_compare_and_swap(&pivs[npiv[OFFSET]], NULL, npiv); cfs = mat->cf_qq[npiv[COEFFS]]; } while (k == 0); cfs = NULL; } /* we do not need the old pivots anymore */ for (i = 0; i < ncl; ++i) { free(pivs[i]); pivs[i] = NULL; } len_t npivs = 0; /* number of new pivots */ for (i = ncols; i < drlen; ++i) { mpz_clear(dr[i]); } dr = realloc(dr, (unsigned long)ncols * sizeof(mpz_t)); mat->tr = realloc(mat->tr, (unsigned long)ncr * sizeof(hm_t *)); /* interreduce new pivots */ mpz_t *cfs; hm_t cf_array_pos; for (i = 0; i < ncr; ++i) { k = ncols-1-i; if (pivs[k]) { for (j = 0; j < ncols; ++j) { mpz_set_si(dr[j], 0); } cfs = mat->cf_qq[pivs[k][COEFFS]]; cf_array_pos = pivs[k][COEFFS]; const len_t os = pivs[k][PRELOOP]; const len_t len = pivs[k][LENGTH]; const hm_t * const ds = pivs[k] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { mpz_swap(dr[ds[j]], cfs[j]); mpz_clear(cfs[j]); } for (; j < len; j += UNROLL) { mpz_swap(dr[ds[j]], cfs[j]); mpz_clear(cfs[j]); mpz_swap(dr[ds[j+1]], cfs[j+1]); mpz_clear(cfs[j+1]); mpz_swap(dr[ds[j+2]], cfs[j+2]); mpz_clear(cfs[j+2]); mpz_swap(dr[ds[j+3]], cfs[j+3]); mpz_clear(cfs[j+3]); } free(pivs[k]); free(cfs); pivs[k] = NULL; pivs[k] = mat->tr[npivs] = reduce_dense_row_by_known_pivots_sparse_qq( dr, mat, bs, pivs, sc, cf_array_pos); remove_content_of_sparse_matrix_row_qq( mat->cf_qq[mat->tr[npivs][COEFFS]], mat->tr[npivs][PRELOOP], mat->tr[npivs][LENGTH]); npivs++; } } free(pivs); pivs = NULL; for (i = 0; i < ncols; ++i) { mpz_clear(dr[i]); } free(dr); dr = NULL; mat->tr = realloc(mat->tr, (unsigned long)npivs * sizeof(hi_t *)); mat->np = mat->nr = mat->sz = npivs; } static void exact_sparse_linear_algebra_ab_first_qq( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* allocate temporary storage space for sparse * coefficients of new pivot rows */ mat->cf_qq = realloc(mat->cf_qq, (unsigned long)mat->nrl * sizeof(mpz_t *)); mat->cf_ab_qq = realloc(mat->cf_ab_qq, (unsigned long)mat->nru * sizeof(mpz_t *)); exact_sparse_reduced_echelon_form_ab_first_qq(mat, bs, st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%7d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static void exact_sparse_linear_algebra_qq( mat_t *mat, const bs_t * const tbr, const bs_t * const bs, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* allocate temporary storage space for sparse * coefficients of new pivot rows */ mat->cf_qq = realloc(mat->cf_qq, (unsigned long)mat->nrl * sizeof(mpz_t *)); exact_sparse_reduced_echelon_form_qq(mat, bs, st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->la_ctime += ct1 - ct0; st->la_rtime += rt1 - rt0; st->num_zerored += (mat->nrl - mat->np); if (st->info_level > 1) { printf("%7d new %7d zero", mat->np, mat->nrl - mat->np); fflush(stdout); } } static void interreduce_matrix_rows_qq( mat_t *mat, bs_t *bs, md_t *st, int free_basis ) { len_t i, j, k, l; const len_t nrows = mat->nr; const len_t ncols = mat->nc; /* adjust displaying timings for statistic printout */ if (st->info_level > 1) { printf(" "); } mat->tr = realloc(mat->tr, (unsigned long)ncols * sizeof(hm_t *)); mat->cf_qq = realloc(mat->cf_qq, (unsigned long)ncols * sizeof(mpz_t *)); memset(mat->cf_qq, 0, (unsigned long)ncols * sizeof(mpz_t *)); hm_t **pivs = (hm_t **)calloc((unsigned long)ncols, sizeof(hm_t *)); /* copy coefficient arrays from basis in matrix, maybe * several rows need the same coefficient arrays, but we * cannot share them here. */ for (i = 0; i < nrows; ++i) { pivs[mat->rr[i][OFFSET]] = mat->rr[i]; } mpz_t *dr = (mpz_t *)malloc((unsigned long)ncols * sizeof(mpz_t)); for (i = 0; i < ncols; ++i) { mpz_init(dr[i]); } /* interreduce new pivots */ mpz_t *cfs; /* starting column, coefficient array position in tmpcf */ hm_t sc; k = nrows - 1; for (i = 0; i < ncols; ++i) { l = ncols-1-i; if (pivs[l] != NULL) { for (j = 0; j < ncols; ++j) { mpz_set_si(dr[j], 0); } cfs = bs->cf_qq[pivs[l][COEFFS]]; const len_t os = pivs[l][PRELOOP]; const len_t len = pivs[l][LENGTH]; const hm_t * const ds = pivs[l] + OFFSET; sc = ds[0]; for (j = 0; j < os; ++j) { mpz_swap(dr[ds[j]], cfs[j]); } for (; j < len; j += UNROLL) { mpz_swap(dr[ds[j]], cfs[j]); mpz_swap(dr[ds[j+1]], cfs[j+1]); mpz_swap(dr[ds[j+2]], cfs[j+2]); mpz_swap(dr[ds[j+3]], cfs[j+3]); } free(pivs[l]); pivs[l] = NULL; pivs[l] = mat->tr[k--] = reduce_dense_row_by_known_pivots_sparse_qq( dr, mat, bs, pivs, sc, l); } } if (free_basis != 0) { /* free now all polynomials in the basis and reset bs->ld to 0. */ free_basis_elements(bs); } free(mat->rr); mat->rr = NULL; mat->np = nrows; free(pivs); for (i = 0; i < ncols; ++i) { mpz_clear(dr[i]); } free(dr); } msolve-0.6.5/src/neogb/libneogb.h000066400000000000000000000020371456710632100166510ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef LIBNEOGB_H #define LIBNEOGB_H #include "data.h" #include "basis.h" #include "engine.h" #include "f4.h" #include "sba.h" #include "hash.h" #include "io.h" #include "modular.h" #include "nf.h" #include "f4sat.h" #include "meta_data.h" #include "sort_r.h" #include "tools.h" #include "update.h" #endif msolve-0.6.5/src/neogb/meta_data.c000066400000000000000000000300761456710632100170060ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "meta_data.h" static md_t *copy_meta_data( const md_t * const gmd, const int32_t prime ) { md_t *md = (md_t *)malloc(sizeof(md_t)); memcpy(md, gmd, sizeof(md_t)); md->fc = prime; md->min_deg_in_first_deg_fall = gmd->min_deg_in_first_deg_fall; md->application_nr_mult = 0; md->application_nr_add = 0; md->application_nr_red = 0; if (md->fc < pow(2,7)) { md->ff_bits = 8; } else { if (md->fc < pow(2,15)) { md->ff_bits = 16; } else { if (md->fc < pow(2,31)) { md->ff_bits = 32; } } } set_ff_bits(md, md->fc); return md; } void free_meta_data( md_t **mdp ) { md_t *md = *mdp; if (md->ps != NULL) { free_pairset(&(md->ps)); } free(md->hcm); ht_t *ht = md->ht; if (ht != NULL) { free_hash_table(&ht); } free(md); md = NULL; *mdp = md; } md_t *allocate_meta_data( void ) { md_t *md = (md_t *)calloc(1, sizeof(md_t)); return md; } void print_tracer_statistics( FILE *file, const double rt, const md_t *st ) { if (st->trace_level == APPLY_TRACER) { if(st->info_level > 1){ fprintf(stderr, "Learning phase %.2f Gops/sec\n", (st->trace_nr_add+st->trace_nr_mult)/1000.0/1000.0/(realtime()-rt)); } if(st->info_level > 2){ fprintf(stderr, "------------------------------------------\n"); fprintf(stderr, "#ADDITIONS %13lu\n", (unsigned long)st->trace_nr_add * 1000); fprintf(stderr, "#MULTIPLICATIONS %13lu\n", (unsigned long)st->trace_nr_mult * 1000); fprintf(stderr, "#REDUCTIONS %13lu\n", (unsigned long)st->trace_nr_red); fprintf(stderr, "------------------------------------------\n"); } } } void print_initial_statistics( FILE *file, const md_t *st ) { if (st->info_level > 0) { fprintf(file, "\n--------------- INPUT DATA ---------------\n"); fprintf(file, "#variables %11d\n", st->nvars); fprintf(file, "#equations %11d\n", st->ngens); fprintf(file, "#invalid equations %11d\n", st->ngens_invalid); fprintf(file, "field characteristic %11u\n", st->fc); fprintf(file, "homogeneous input? %11d\n", st->homogeneous); fprintf(file, "signature-based computation %6d\n", st->use_signatures); if (st->mo == 0 && st->nev == 0) { fprintf(file, "monomial order DRL\n"); } if (st->mo == 0 && st->nev > 0) { fprintf(file, "monomial order ELIM(%d)\n", st->nev); } if (st->mo == 1 && st->nev == 0) { fprintf(file, "monomial order LEX\n"); } if ((st->mo != 0) && (st->mo != 1)) { fprintf(file, "monomial order DONT KNOW\n"); } if (st->reset_ht == 2147483647) { fprintf(file, "basis hash table resetting OFF\n"); } else { fprintf(file, "basis hash table resetting %6d\n", st->reset_ht); } fprintf(file, "linear algebra option %11d\n", st->laopt); fprintf(file, "initial hash table size %10lu (2^%d)\n", (unsigned long)pow(2,st->init_hts), st->init_hts); if (st->mnsel == 2147483647) { fprintf(file, "max pair selection ALL\n"); } else { fprintf(file, "max pair selection %11d\n", st->mnsel); } fprintf(file, "reduce gb %11d\n", st->reduce_gb); fprintf(file, "#threads %11d\n", st->nthrds); fprintf(file, "info level %11d\n", st->info_level); fprintf(file, "generate pbm files %11d\n", st->gen_pbm_file); fprintf(file, "------------------------------------------\n"); } } void print_round_information_header( FILE *f, const md_t * const st ) { if (st->info_level > 1) { if (st->trace_level != APPLY_TRACER) { fprintf(f, "\n"); fprintf(f, "Legend for f4 information\n"); fprintf(f, "--------------------------------------------------------\n"); fprintf(f, "deg current degree of pairs selected in this round\n"); fprintf(f, "sel number of pairs selected in this round\n"); fprintf(f, "pairs total number of pairs in pair list\n"); fprintf(f, "mat matrix dimensions (# rows x # columns)\n"); fprintf(f, "density density of the matrix\n"); fprintf(f, "new data # new elements for basis in this round\n"); fprintf(f, " # zero reductions during linear algebra\n"); fprintf(f, "time(rd) time of the current f4 round in seconds given\n"); fprintf(f, " for real and cpu time\n"); fprintf(f, "--------------------------------------------------------\n"); fprintf(f, "\ndeg sel pairs mat density \ new data time(rd) in sec (real|cpu)\n"); fprintf(f, "-------------------------------------------------\ -----------------------------------------------------\n"); } else { fprintf(f, "Legend for f4 information\n"); fprintf(f, "--------------------------------------------------------\n"); fprintf(f, "round # of current tracer round\n"); fprintf(f, "deg current degree of pairs selected in this round\n"); fprintf(f, "mat matrix dimensions (# rows x # columns)\n"); fprintf(f, "density density of the matrix\n"); fprintf(f, "new data # new elements for basis in this round\n"); fprintf(f, " # zero reductions during linear algebra\n"); fprintf(f, "time(rd) time of the current f4 round in seconds given\n"); fprintf(f, " for real and cpu time\n"); fprintf(f, "--------------------------------------------------------\n"); fprintf(f, "\n round deg mat density \ new data time(rd) in sec (real|cpu)\n"); fprintf(f, "-------------------------------------------------\ -----------------------------------------------------\n"); } } } void print_sat_nf_round_timings( FILE *f, const md_t * const st, const double rrt, const double crt ) { if (st->info_level > 1) { printf("%15.2f | %-13.2f\n", realtime() - rrt, cputime() - crt); } } void print_sat_round_timings( FILE *f, const md_t * const st, const double rrt, const double crt ) { if (st->info_level > 1) { printf("%10.2f | %-13.2f\n", realtime() - rrt, cputime() - crt); } } void print_round_timings( FILE *f, const md_t * const st, const double rrt, const double crt ) { if (st->info_level > 1) { printf("%13.2f | %-13.2f\n", realtime() - rrt, cputime() - crt); } } void print_round_information_footer( FILE *f, const md_t * const st ) { if (st->info_level > 1) { printf("-------------------------------------------------\ -----------------------------------------------------\n"); } } static void print_current_trace_meta_data( md_t *md ) { len_t rd = md->trace_rd; len_t deg = md->tr->td[rd].deg; if (md->info_level > 1) { printf("%9d %6d ", rd+1, deg); fflush(stdout); } } static void get_final_statistics( md_t *md, const bs_t * const bs ) { len_t i = 0; int64_t nterms = 0; md->size_basis = bs->lml; for (i = 0; i < bs->lml; ++i) { if (bs->hm[bs->lmps[i]] == NULL) { nterms++; } else { nterms += bs->hm[bs->lmps[i]][LENGTH]; } } md->nterms_basis = nterms; } void get_and_print_final_statistics( FILE *file, md_t *st, const bs_t * const bs ) { get_final_statistics(st, bs); if (st->info_level > 0) { fprintf(file, "\n---------------- TIMINGS ---------------\n"); fprintf(file, "overall(elapsed) %11.2f sec\n", st->f4_rtime); fprintf(file, "overall(cpu) %15.2f sec\n", st->f4_ctime); if(st->trace_level == APPLY_TRACER) { fprintf(file, "tracer %15.2f sec %5.1f%%\n", st->tracer_rtime, (double)100*(double)st->tracer_rtime / (double)(st->f4_rtime)); } else { fprintf(file, "select %15.2f sec %5.1f%%\n", st->select_rtime, (double)100*(double)st->select_rtime / (double)(st->f4_rtime)); fprintf(file, "symbolic prep. %7.2f sec %5.1f%%\n", st->symbol_rtime, (double)100*(double)st->symbol_rtime / (double)(st->f4_rtime)); fprintf(file, "update %15.2f sec %5.1f%%\n", st->update_rtime, (double)100*(double)st->update_rtime / (double)(st->f4_rtime)); } fprintf(file, "convert %15.2f sec %5.1f%%\n", st->convert_rtime, (double)100*(double)st->convert_rtime / (double)(st->f4_rtime)); fprintf(file, "linear algebra %11.2f sec %5.1f%%\n", st->la_rtime, (double)100*(double)st->la_rtime / (double)(st->f4_rtime)); if (st->reduce_gb == 1) { fprintf(file, "reduce gb %15.2f sec %5.1f%%\n", st->reduce_gb_rtime, (double)100*(double)st->reduce_gb_rtime / (double)(st->f4_rtime)); } if (st->reset_ht != 2147483647) { fprintf(file, "rht %15.2f sec %5.1f%%\n", st->rht_rtime, (double)100*(double)st->rht_rtime / (double)(st->f4_rtime)); } fprintf(file, "-----------------------------------------\n"); fprintf(file, "\n---------- COMPUTATIONAL DATA -----------\n"); fprintf(file, "size of basis %16lu\n", (unsigned long)st->size_basis); fprintf(file, "#terms in basis %16lu\n", (unsigned long)st->nterms_basis); fprintf(file, "#pairs reduced %16lu\n", (unsigned long)st->num_pairsred); fprintf(file, "#GM criterion %16lu\n", (unsigned long)st->num_gb_crit); fprintf(file, "#redundant elements %10lu\n", (unsigned long)st->num_redundant); fprintf(file, "#rows reduced %16lu\n", (unsigned long)st->num_rowsred); fprintf(file, "#zero reductions %16lu\n", (unsigned long)st->num_zerored); fprintf(file, "max. matrix data %16ld x %ld (%.3f%%)\n", (long)st->mat_max_nrows, (long)st->mat_max_ncols, st->mat_max_density); fprintf(file, "max. symbolic hash table size 2^%d\n", (int32_t)(ceil(log((double)st->max_sht_size)/log(2)))); fprintf(file, "max. basis hash table size 2^%d\n", (int32_t)(ceil(log((double)st->max_bht_size)/log(2)))); fprintf(file, "-----------------------------------------\n\n"); } } msolve-0.6.5/src/neogb/meta_data.h000066400000000000000000000025131456710632100170060ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef GB_META_DATA_H #define GB_META_DATA_H #include "data.h" md_t *allocate_meta_data( void ); void print_initial_statistics( FILE *, const md_t *md ); void print_tracer_statistics( FILE *, const double rt, const md_t *md ); void get_and_print_final_statistics( FILE *file, md_t *md, const bs_t * const bs ); #endif msolve-0.6.5/src/neogb/modular.c000066400000000000000000002222301456710632100165250ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "modular.h" static int minimal_traced_lm_is_equal( const hm_t *lmh, const len_t lml, const bs_t *bs ) { if (bs->lml != lml) { return 0; } len_t i = 0; for (i = 0; i < lml; ++i) { if (bs->hm[bs->lmps[i]][OFFSET] != lmh[i]) { return 0; } } return 1; } trace_t *initialize_trace( const bs_t * const bs, const md_t * const md ) { trace_t *tr = (trace_t *)calloc(1, sizeof(trace_t)); tr->std = 8; tr->sts = 8; tr->ltd = 0; tr->lts = 0; tr->td = calloc((unsigned long)tr->std, sizeof(td_t)); tr->ts = calloc((unsigned long)tr->sts, sizeof(ts_t)); /* rounds stuff for f4sat */ tr->rsz = 8; tr->rld = 0; tr->rd = calloc((unsigned long)tr->rsz, sizeof(len_t)); return tr; } void free_trace( trace_t **trp ) { trace_t *tr = *trp; if (tr != NULL) { len_t i, j; for (i = 0; i < tr->lts; ++i) { free(tr->ts[i].tri); free(tr->ts[i].rri); free(tr->ts[i].nlms); /* free(tr->ts[i].lmh); */ } for (i = 0; i < tr->ltd; ++i) { free(tr->td[i].tri); free(tr->td[i].rri); for (j = 0; j < tr->td[i].tld/2; ++j) { free(tr->td[i].rba[j]); } free(tr->td[i].rba); free(tr->td[i].nlms); } free(tr->lm); free(tr->lmh); free(tr->lmps); free(tr->ts); free(tr->td); free(tr->rd); free(tr); tr = NULL; *trp = tr; } } void free_lucky_primes( primes_t **lpp ) { primes_t *lp = *lpp; free(lp->p); free(lp); lp = NULL; *lpp = lp; } /* keeps bht since we know most of the basis already, * unlike the reduce_basis() function in f4.c */ void reduce_basis_no_hash_table_switching( bs_t *bs, mat_t *mat, ht_t *bht, ht_t *sht, md_t *st ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); len_t i, j, k; exp_t *etmp = bht->ev[0]; memset(etmp, 0, (unsigned long)(bht->evl) * sizeof(exp_t)); mat->rr = (hm_t **)malloc((unsigned long)bs->lml * 2 * sizeof(hm_t *)); mat->nr = mat->nc = mat->ncl = mat->ncr = 0; mat->sz = 2 * bs->lml; /* add all non-redundant basis elements as matrix rows */ for (i = 0; i < bs->lml; ++i) { mat->rr[mat->nr] = multiplied_poly_to_matrix_row( sht, bht, 0, etmp, bs->hm[bs->lmps[i]]); sht->hd[mat->rr[mat->nr][OFFSET]].idx = 1; mat->nr++; } mat->nc = mat->nr; /* needed for correct counting in symbol */ symbolic_preprocessing(mat, bs, st); /* no known pivots, we need mat->ncl = 0, so set all indices to 1 */ for (i = 0; i < sht->eld; ++i) { sht->hd[i].idx = 1; } /* generate hash <-> column mapping */ if (st->info_level > 1) { printf("reduce basis "); fflush(stdout); } convert_hashes_to_columns(mat, st, sht); mat->nc = mat->ncl + mat->ncr; /* sort rows */ sort_matrix_rows_decreasing(mat->rr, mat->nru); /* do the linear algebra reduction and free basis data */ interreduce_matrix_rows(mat, bs, st, 1); /* remap rows to basis elements (keeping their position in bs) */ convert_sparse_matrix_rows_to_basis_elements( 1, mat, bs, bht, sht, st); bs->ld = mat->np; /* clean_hash_table(sht); */ clear_matrix(mat); /* we may have added some multiples of reduced basis polynomials * from the matrix, so we get rid of them. */ k = 0; i = 0; start: for (; i < bs->ld; ++i) { for (j = 0; j < k; ++j) { if (check_monomial_division( bs->hm[bs->ld-1-i][OFFSET], bs->hm[bs->lmps[j]][OFFSET], bht)) { ++i; goto start; } } bs->lmps[k++] = bs->ld-1-i; } bs->lml = k; /* timings */ ct1 = cputime(); rt1 = realtime(); st->reduce_gb_ctime = ct1 - ct0; st->reduce_gb_rtime = rt1 - rt0; if (st->info_level > 1) { printf("%13.2f sec\n", rt1-rt0); } if (st->info_level > 1) { printf("-------------------------------------------------\ ----------------------------------------\n"); } } /* applies tracer, if prime is unlucky NULL is returned */ bs_t *f4_trace_application_phase( const trace_t * const trace, /* trace of the F4 Algorithm */ const ht_t * const tht, /* trace hash table for multipliers */ const bs_t * const ggb, /* global basis */ ht_t *lbht, /* local basis hash table, not shared */ md_t *gst, /* global statistics */ const uint32_t fc /* characteristic of field */ ) { /* timings */ double ct0, ct1, rt0, rt1; double rrt0, rrt1; /* for one round only */ ct0 = cputime(); rt0 = realtime(); int32_t round, i; /* hashes-to-columns map, initialized with length 1, is reallocated * in each call when generating matrices for linear algebra */ hi_t *hcm = (hi_t *)malloc(sizeof(hi_t)); /* set routines corresponding to prime size */ reset_trace_function_pointers(fc); /* matrix holding sparse information generated * during symbolic preprocessing */ mat_t *mat = (mat_t *)calloc(1, sizeof(mat_t)); /* copy global data as input */ md_t *st = copy_meta_data(gst, fc); bs_t *bs = copy_basis_mod_p(ggb, st); ht_t *bht = lbht; /* normalize the copied basis */ normalize_initial_basis(bs, fc); /* initialize specialized hash table */ ht_t *sht = initialize_secondary_hash_table(bht, st); int32_t ret = 0; /* reset bs->ld for first update process */ bs->ld = st->ngens; if(st->info_level>1){ printf("Application phase with prime p = %d, overall there are %u rounds\n", fc, trace->ltd); } /* let's start the f4 rounds, we are done when no more spairs * are left in the pairset */ if (st->info_level > 1) { printf("\nround deg mat density \ new data time(rd)\n"); printf("-------------------------------------------------\ ----------------------------------------\n"); } for (round = 0; round < trace->ltd; ++round) { rrt0 = realtime(); st->max_bht_size = st->max_bht_size > bht->esz ? st->max_bht_size : bht->esz; st->current_rd = round; /* generate matrix out of tracer data, rows are then already * sorted correspondingly */ generate_matrix_from_trace(mat, bs, st); if (st->info_level > 1) { printf("%5d", round+1); printf("%6u ", sht->ev[mat->tr[0][OFFSET]][DEG]); fflush(stdout); } convert_hashes_to_columns(mat, st, sht); /* linear algebra, depending on choice, see set_function_pointers() */ ret = application_linear_algebra(mat, bs, st); if (ret != 0) { goto stop; } /* columns indices are mapped back to exponent hashes */ if (mat->np > 0) { if (mat->np != trace->td[round].nlm) { fprintf(stderr, "Wrong number of new elements when applying tracer."); ret = 1; goto stop; } convert_sparse_matrix_rows_to_basis_elements( -1, mat, bs, bht, sht, st); for (i = 0; i < mat->np; ++i) { if (bs->hm[bs->ld+i][OFFSET] != trace->td[round].nlms[i]) { fprintf(stderr, "Wrong leading term for new element %u/%u.", i, mat->np); ret = 1; goto stop; } } } bs->ld += mat->np; clean_hash_table(sht); /* all rows in mat are now polynomials in the basis, * so we do not need the rows anymore */ clear_matrix(mat); rrt1 = realtime(); if (st->info_level > 1) { printf("%13.2f sec\n", rrt1-rrt0); } } if (st->info_level > 1) { printf("-------------------------------------------------\ ----------------------------------------\n"); } /* apply non-redundant basis data from trace to basis * before interreduction */ bs->lml = trace->lml; free(bs->lmps); bs->lmps = (bl_t *)calloc((unsigned long)bs->lml, sizeof(bl_t)); memcpy(bs->lmps, trace->lmps, (unsigned long)bs->lml * sizeof(bl_t)); free(bs->lm); bs->lm = (sdm_t *)calloc((unsigned long)bs->lml, sizeof(sdm_t)); memcpy(bs->lm, trace->lm, (unsigned long)bs->lml * sizeof(sdm_t)); #if 0 /* eliminate variables if accessible */ len_t j = 0; if (st->nev > 0) { j = 0; for (i = 0; i < bs->lml; ++i) { if (bht->ev[bs->hm[bs->lmps[i]][OFFSET]][0] == 0) { bs->lm[j] = bs->lm[i]; bs->lmps[j] = bs->lmps[i]; ++j; } } bs->lml = j; } #endif /* reduce final basis */ /* note: bht will become sht, and sht will become NULL, * thus we need pointers */ reduce_basis_no_hash_table_switching( bs, mat, bht, sht, st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->f4_ctime = ct1 - ct0; st->f4_rtime = rt1 - rt0; /* get basis meta data */ st->size_basis = bs->lml; for (i = 0; i < bs->lml; ++i) { st->nterms_basis += (int64_t)bs->hm[bs->lmps[i]][LENGTH]; } get_and_print_final_statistics(stderr, st, bs); stop: /* free and clean up */ free(hcm); if (sht != NULL) { free_hash_table(&sht); } /* note that all rows kept from mat during the overall computation are * basis elements and thus we do not need to free the rows itself, but * just the matrix structure */ free(mat); gst->application_nr_add = st->application_nr_add; gst->application_nr_mult = st->application_nr_mult; gst->application_nr_red = st->application_nr_red; free(st); if (ret != 0) { free_basis(&bs); } return bs; } bs_t *f4sat_trace_application_test_phase( const trace_t * const trace, /* trace of the F4 Algorithm */ const ht_t * const tht, /* trace hash table for multipliers */ const bs_t * const ggb, /* global basis */ const bs_t * const gsat, /* global saturation element */ ht_t *lbht, /* local basis hash table, not shared */ md_t *gst, /* global statistics */ const uint32_t fc /* characteristic of field */ ) { /* timings */ double ct0, ct1, rt0, rt1; double rrt0, rrt1; /* for one round only */ ct0 = cputime(); rt0 = realtime(); ps_t * ps = initialize_pairset(); /* current quotient basis up to max lm degree in intermediate basis */ hm_t *qb = NULL; int32_t round, ctr, i, j; ctr = 0; /* hashes-to-columns maps for multipliers in saturation step */ hi_t *hcmm = (hi_t *)malloc(sizeof(hi_t)); /* set routines corresponding to prime size */ reset_trace_function_pointers(fc); /* matrix holding sparse information generated * during symbolic preprocessing */ mat_t *mat = (mat_t *)calloc(1, sizeof(mat_t)); /* copy global data as input */ md_t *st = copy_meta_data(gst, fc); bs_t *bs = copy_basis_mod_p(ggb, st); bs_t *sat = copy_basis_mod_p(gsat, st); ht_t *bht = lbht; /* initialize multiplier of first element in sat to be the hash of * the all-zeroes exponent vector. */ memset(bht->ev[0], 0, (unsigned long)(bht->evl) * sizeof(exp_t)); sat->hm[0][MULT] = insert_in_hash_table(bht->ev[0], bht); sat->ld = 1; len_t sat_deg = 0; /* normalize the copied basis */ normalize_initial_basis(bs, fc); /* initialize specialized hash table */ ht_t *sht = initialize_secondary_hash_table(bht, st); /* elements of kernel in saturation step, to be added to basis bs */ bs_t *kernel = initialize_basis(st); /* reset bs->ld for first update process */ bs->ld = 0; /* move input generators to basis and generate first spairs. * always check redundancy since input generators may be redundant * even so they are homogeneous. */ update_basis_f4(ps, bs, bht, st, st->ngens); if(st->info_level>1){ printf("Application phase with prime p = %d, overall there are %u rounds\n", fc, trace->ltd); } /* let's start the f4 rounds, we are done when no more spairs * are left in the pairset */ if (st->info_level > 1) { printf("\ndeg sel pairs mat density \ new data time(rd)\n"); printf("-------------------------------------------------\ ----------------------------------------\n"); } round = 1; for (; ps->ld > 0; ++round) { if (round % st->reset_ht == 0) { reset_hash_table(bht, bs, ps, st); st->num_rht++; } rrt0 = realtime(); st->max_bht_size = st->max_bht_size > bht->esz ? st->max_bht_size : bht->esz; st->current_rd = round; /* preprocess data for next reduction round */ select_spairs_by_minimal_degree(mat, bs, st); symbolic_preprocessing(mat, bs, st); convert_hashes_to_columns(mat, st, sht); sort_matrix_rows_decreasing(mat->rr, mat->nru); sort_matrix_rows_increasing(mat->tr, mat->nrl); /* print pbm files of the matrices */ if (st->gen_pbm_file != 0) { write_pbm_file(mat, st); } /* linear algebra, depending on choice, see set_function_pointers() */ exact_sparse_linear_algebra_ff_32(mat, bs, bs, st); /* columns indices are mapped back to exponent hashes */ if (mat->np > 0) { convert_sparse_matrix_rows_to_basis_elements( -1, mat, bs, bht, sht, st); } /* all rows in mat are now polynomials in the basis, * so we do not need the rows anymore */ clear_matrix(mat); // does not reset mat->np update_basis_f4(ps, bs, bht, st, mat->np); /* if we found a constant we are done, so remove all remaining pairs */ rrt1 = realtime(); if (st->info_level > 1) { printf("%13.2f sec\n", rrt1-rrt0); } if (bs->constant == 1) { printf("basis is constant\n"); ps->ld = 0; break; } clean_hash_table(sht); /* saturation step starts here */ if (trace->rd[ctr] == round-1) { rrt0 = realtime(); /* printf("sat->deg %u\n", sat_deg); */ update_multipliers(&qb, &bht, &sht, sat, st, bs, sat_deg); /* check for monomial multiples of elements from saturation list */ select_saturation(sat, mat, st, sht, bht); symbolic_preprocessing(mat, bs, st); /* It may happen that there is no reducer at all for the * saturation elements, then nothing has to be done. */ if (mat->nru > 0) { if (st->info_level > 1) { /* printf("kernel computation "); */ printf("%3u compute kernel", sat_deg); } /* int ctr = 0; * for (int ii = 1; ii < sat->ld; ++ii) { * for (int jj = 0; jj < ii; jj++) { * if (sat->hm[ii][MULT] == sat->hm[jj][MULT]) { * printf("MULT %d == %d\n", ii, jj); * ctr++; * } * } * } */ /* int ctr = 0; * for (int ii = 0; iild; ++ii) { * if (sht->hd[sat->hm[ii][OFFSET]].idx == 2) { * sat->hm[ctr] = sat->hm[ii]; * } else { * free(sat->hm[ii]); * sat->hm[ii] = NULL; * } * } * sat->ld = ctr; */ convert_hashes_to_columns_sat(mat, sat, st, sht); convert_multipliers_to_columns(&hcmm, sat, st, bht); sort_matrix_rows_decreasing(mat->rr, mat->nru); compute_kernel_sat_ff_32(sat, mat, kernel, bs, st); if (kernel->ld > 0) { if (st->info_level > 1) { printf("\n "); } clear_matrix(mat); /* interreduce kernel */ copy_kernel_to_matrix(mat, kernel, sat->ld); /* linear algebra, depending on choice, see set_function_pointers() */ exact_sparse_linear_algebra_ff_32(mat, kernel, kernel, st); /* columns indices are mapped back to exponent hashes */ if (mat->np > 0) { /* use the correct hcmm for kernel elements! */ hi_t *tmp = st->hcm; st->hcm = hcmm; convert_sparse_matrix_rows_to_basis_elements_use_sht( -1, mat, bs, bht, st); st->hcm = tmp; } st->nr_kernel_elts += kernel->ld; free_kernel_coefficients(kernel); update_basis_f4(ps, bs, bht, st, mat->np); kernel->ld = 0; if (st->info_level > 1) { printf(" "); } } /* columns indices are mapped back to exponent hashes */ /* return_normal_forms_to_basis( * mat, tbr, bht, sht, hcm, st); */ /* all rows in mat are now polynomials in the basis, * so we do not need the rows anymore */ convert_columns_to_hashes(sat, st, hcmm); for (i = 0; i < sat->ld; ++i) { bht->hd[hcmm[i]].idx = 0; } } clear_matrix(mat); /* move hashes for sat entries from sht back to bht */ for (i = 0; i < sat->ld; ++i) { if (sat->hm[i] != NULL) { while (bht->esz - bht->eld < sat->hm[i][LENGTH]) { enlarge_hash_table(bht); } for (j = OFFSET; j < sat->hm[i][LENGTH]+OFFSET; ++j) { sat->hm[i][j] = insert_in_hash_table( sht->ev[sat->hm[i][j]], bht); } deg_t deg = bht->hd[sat->hm[i][OFFSET]].deg; if (st->nev > 0) { const len_t len = sat->hm[i][LENGTH]+OFFSET; for (j = OFFSET+1; j < len; ++j) { if (deg < bht->hd[sat->hm[i][j]].deg) { deg = bht->hd[sat->hm[i][j]].deg; } } } sat->hm[i][DEG] = deg; } } clean_hash_table(sht); rrt1 = realtime(); if (st->info_level > 1) { printf("%10.2f sec\n", rrt1-rrt0); } } } if (st->info_level > 1) { printf("-------------------------------------------------\ ----------------------------------------\n"); } /* remove possible redudant elements */ final_remove_redundant_elements(bs, st, bht); /* apply non-redundant basis data from trace to basis * before interreduction */ bs->lml = trace->lml; free(bs->lmps); bs->lmps = (bl_t *)calloc((unsigned long)bs->lml, sizeof(bl_t)); memcpy(bs->lmps, trace->lmps, (unsigned long)bs->lml * sizeof(bl_t)); free(bs->lm); bs->lm = (sdm_t *)calloc((unsigned long)bs->lml, sizeof(sdm_t)); memcpy(bs->lm, trace->lm, (unsigned long)bs->lml * sizeof(sdm_t)); /* reduce final basis */ /* note: bht will become sht, and sht will become NULL, * thus we need pointers */ reduce_basis_no_hash_table_switching( bs, mat, bht, sht, st); /* timings */ ct1 = cputime(); rt1 = realtime(); st->f4_ctime = ct1 - ct0; st->f4_rtime = rt1 - rt0; /* get basis meta data */ st->size_basis = bs->lml; for (i = 0; i < bs->lml; ++i) { st->nterms_basis += (int64_t)bs->hm[bs->lmps[i]][LENGTH]; } get_and_print_final_statistics(stderr, st, bs); /* free and clean up */ free(hcmm); free_basis_elements(sat); free_basis(&sat); free_basis(&kernel); /* note that all rows kept from mat during the overall computation are * basis elements and thus we do not need to free the rows itself, but * just the matrix structure */ free(mat); gst->application_nr_add = st->application_nr_add; gst->application_nr_mult = st->application_nr_mult; gst->application_nr_red = st->application_nr_red; free_meta_data(&st); return bs; } bs_t *f4sat_trace_application_phase( const trace_t * const trace, /* trace of the F4 Algorithm */ const ht_t * const tht, /* trace hash table for multipliers */ const bs_t * const ggb, /* global basis */ const bs_t * const gsat, /* global saturation element */ ht_t *lbht, /* local basis hash table, not shared */ md_t *gst, /* global statistics */ const uint32_t fc /* characteristic of field */ ) { /* timings */ double ct = cputime(); double rt = realtime(); double rrt, crt; /* for one round only */ /* current quotient basis up to max lm degree in intermediate basis */ hm_t *qb = NULL; int32_t round, ctr, i, j; ctr = 0; len_t ts_ctr = 0; int32_t ret = 0; /* hashes-to-columns maps for multipliers in saturation step */ hi_t *hcmm = (hi_t *)malloc(sizeof(hi_t)); /* matrix holding sparse information generated * during symbolic preprocessing */ mat_t *mat = (mat_t *)calloc(1, sizeof(mat_t)); /* copy global data as input */ md_t *st = copy_meta_data(gst, fc); bs_t *bs = copy_basis_mod_p(ggb, st); bs_t *sat = copy_basis_mod_p(gsat, st); ht_t *bht = bs->ht; st->trace_level = APPLY_TRACER; /* set routines corresponding to prime size */ reset_function_pointers(fc, st->laopt); /* initialize multiplier of first element in sat to be the hash of * the all-zeroes exponent vector. */ exp_t zero[bht->evl];; memset(zero, 0, (unsigned long)(bht->evl) * sizeof(exp_t)); sat->hm[0][MULT] = insert_in_hash_table(zero, bht); sat->ld = 1; len_t sat_deg = 0; /* normalize the copied basis */ normalize_initial_basis(bs, fc); /* initialize specialized hash table */ ht_t *sht = initialize_secondary_hash_table(bht, st); st->ht = sht; /* elements of kernel in saturation step, to be added to basis bs */ bs_t *kernel = initialize_basis(st); bs->ld = st->ngens; update_lm(bs, bht, st); if(st->info_level>1){ printf("Application phase with prime p = %d\n%u f4 rounds and %u saturation rounds\n", fc, trace->ltd, trace->rld); } /* let's start the f4 rounds, we are done when no more spairs * are left in the pairset */ print_round_information_header(stdout, st); round = 0; for (; round < trace->ltd; ++round) { rrt = realtime(); crt = cputime(); st->max_bht_size = st->max_bht_size > bht->esz ? st->max_bht_size : bht->esz; st->current_rd = round; /* generate matrix out of tracer data, rows are then already * sorted correspondingly */ generate_matrix_from_trace(mat, bs, st); st->trace_rd++; /* if (st->info_level > 1) { printf("%5d", round+1); printf("%6u ", sht->ev[mat->tr[0][OFFSET]][DEG]); fflush(stdout); } */ convert_hashes_to_columns(mat, st, sht); /* linear algebra, depending on choice, see set_function_pointers() */ linear_algebra(mat, bs, bs, st); if (ret != 0) { goto stop; } /* columns indices are mapped back to exponent hashes */ if (mat->np > 0) { if (mat->np != trace->td[round].nlm) { fprintf(stderr, "Wrong number of new elements when applying tracer."); ret = 1; goto stop; } convert_sparse_matrix_rows_to_basis_elements( -1, mat, bs, bht, sht, st); for (i = 0; i < mat->np; ++i) { if (bs->hm[bs->ld+i][OFFSET] != trace->td[round].nlms[i]) { fprintf(stderr, "Wrong leading term for new element %u/%u.", i, mat->np); ret = 1; goto stop; } } bs->ld += mat->np; update_lm(bs, bht, st); } clean_hash_table(sht); /* all rows in mat are now polynomials in the basis, * so we do not need the rows anymore */ clear_matrix(mat); print_round_timings(stdout, st, rrt, crt); /* saturation step starts here */ while (ctr < trace->rld && trace->rd[ctr] == round) { ctr++; sat_deg = trace->ts[ts_ctr].deg; /* check for new elements to be tested for adding saturation * information to the intermediate basis */ rrt = realtime(); crt = cputime(); update_multipliers(&qb, &bht, &sht, sat, st, bs, sat_deg); /* check for monomial multiples of elements from saturation list */ select_saturation(sat, mat, st, sht, bht); generate_saturation_reducer_rows_from_trace(mat, trace, ts_ctr, bs, st, sht, bht); ts_ctr++; /* symbolic_preprocessing(mat, bs, st, sht, NULL, bht); */ /* It may happen that there is no reducer at all for the * saturation elements, then nothing has to be done. */ if (mat->nru > 0) { if (st->info_level > 1) { /* printf("kernel computation "); */ printf("sat %5u %7u ", ctr, sat_deg); } /* int ctr = 0; * for (int ii = 1; ii < sat->ld; ++ii) { * for (int jj = 0; jj < ii; jj++) { * if (sat->hm[ii][MULT] == sat->hm[jj][MULT]) { * printf("MULT %d == %d\n", ii, jj); * ctr++; * } * } * } */ /* int ctr = 0; * for (int ii = 0; iild; ++ii) { * if (sht->hd[sat->hm[ii][OFFSET]].idx == 2) { * sat->hm[ctr] = sat->hm[ii]; * } else { * free(sat->hm[ii]); * sat->hm[ii] = NULL; * } * } * sat->ld = ctr; */ convert_hashes_to_columns_sat(mat, sat, st, sht); convert_multipliers_to_columns(&hcmm, sat, st, bht); sort_matrix_rows_decreasing(mat->rr, mat->nru); compute_kernel_sat_ff_32(sat, mat, kernel, bs, st); if (st->info_level > 1) { printf("%56d new kernel elements", kernel->ld); fflush(stdout); printf("\n "); } if (kernel->ld == 0) { fprintf(stderr, "Trivial kernel when applying tracer."); ret = 1; goto stop; } clear_matrix(mat); /* interreduce kernel */ copy_kernel_to_matrix(mat, kernel, sat->ld); /* linear algebra, depending on choice, see set_function_pointers() */ exact_sparse_linear_algebra_ff_32(mat, kernel, kernel, st); /* columns indices are mapped back to exponent hashes */ if (mat->np > 0) { /* use the correct hcmm for kernel elements! */ hi_t *tmp = st->hcm; st->hcm = hcmm; convert_sparse_matrix_rows_to_basis_elements_use_sht( -1, mat, bs, bht, st); st->hcm = tmp; bs->ld += mat->np; update_lm(bs, bht, st); } st->nr_kernel_elts += kernel->ld; free_kernel_coefficients(kernel); kernel->ld = 0; /* all rows in mat are now polynomials in the basis, * so we do not need the rows anymore */ convert_columns_to_hashes(sat, st, hcmm); for (i = 0; i < sat->ld; ++i) { bht->hd[hcmm[i]].idx = 0; } } clear_matrix(mat); /* move hashes for sat entries from sht back to bht */ for (i = 0; i < sat->ld; ++i) { if (sat->hm[i] != NULL) { while (bht->esz - bht->eld < sat->hm[i][LENGTH]) { enlarge_hash_table(bht); } for (j = OFFSET; j < sat->hm[i][LENGTH]+OFFSET; ++j) { sat->hm[i][j] = insert_in_hash_table( sht->ev[sat->hm[i][j]], bht); } deg_t deg = bht->hd[sat->hm[i][OFFSET]].deg; if (st->nev > 0) { const len_t len = sat->hm[i][LENGTH]+OFFSET; for (j = OFFSET+1; j < len; ++j) { if (deg < bht->hd[sat->hm[i][j]].deg) { deg = bht->hd[sat->hm[i][j]].deg; } } } sat->hm[i][DEG] = deg; } } clean_hash_table(sht); print_round_timings(stdout, st, rrt, crt); } } print_round_information_footer(stdout, st); /* apply non-redundant basis data from trace to basis * before interreduction */ bs->lml = trace->lml; free(bs->lmps); bs->lmps = (bl_t *)calloc((unsigned long)bs->lml, sizeof(bl_t)); memcpy(bs->lmps, trace->lmps, (unsigned long)bs->lml * sizeof(bl_t)); free(bs->lm); bs->lm = (sdm_t *)calloc((unsigned long)bs->lml, sizeof(sdm_t)); memcpy(bs->lm, trace->lm, (unsigned long)bs->lml * sizeof(sdm_t)); /* reduce final basis */ /* note: bht will become sht, and sht will become NULL, * thus we need pointers */ reduce_basis_no_hash_table_switching( bs, mat, bht, sht, st); /* timings */ st->f4_ctime = cputime() - ct; st->f4_rtime = realtime() - rt; /* get basis meta data */ st->size_basis = bs->lml; for (i = 0; i < bs->lml; ++i) { st->nterms_basis += (int64_t)bs->hm[bs->lmps[i]][LENGTH]; } get_and_print_final_statistics(stderr, st, bs); stop: /* free and clean up */ free(hcmm); free_basis_without_hash_table(&sat); free_basis(&kernel); /* note that all rows kept from mat during the overall computation are * basis elements and thus we do not need to free the rows itself, but * just the matrix structure */ free(mat); gst->application_nr_add = st->application_nr_add; gst->application_nr_mult = st->application_nr_mult; gst->application_nr_red = st->application_nr_red; free(st); if (ret != 0) { free_basis_without_hash_table(&bs); } return bs; } /* In the learning phase we generate * 1. a groebner basis mod fc, * 2. a trace of the F4 run including a trace hash table tht * 3. a basis hash table (this should be nearly the same for * all further runs of F4, so the subsequent runs just copy * it and we will terms to the global basis hash table if * needed on the fly) */ bs_t *f4_trace_learning_phase( trace_t *trace, /* trace of the F4 Algorithm */ ht_t * tht, /* trace hash table for multipliers */ const bs_t * const ggb, /* global basis */ ht_t *gbht, /* global basis hash table, generated * in this run, used in upcoming runs */ md_t *gst, /* global statistics */ const int32_t fc /* characteristic of field */ ) { /* timings */ double ct0, ct1, rt0, rt1; double rrt0, rrt1; /* for one round only */ ct0 = cputime(); rt0 = realtime(); int32_t round, i; /* hashes-to-columns map, initialized with length 1, is reallocated * in each call when generating matrices for linear algebra */ hi_t *hcm = (hi_t *)malloc(sizeof(hi_t)); /* matrix holding sparse information generated * during symbolic preprocessing */ mat_t *mat = (mat_t *)calloc(1, sizeof(mat_t)); /* set routines corresponding to prime size */ reset_trace_function_pointers(fc); ps_t * ps = initialize_pairset(); /* copy global data as input */ md_t *st = copy_meta_data(gst, fc); bs_t *bs = copy_basis_mod_p(ggb, st); ht_t *bht = gbht; /* normalize the copied basis */ normalize_initial_basis(bs, fc); /* initialize specialized hash tables */ ht_t *sht = initialize_secondary_hash_table(bht, st); /* reset bs->ld for first update process */ bs->ld = 0; /* move input generators to basis and generate first spairs. * always check redundancy since input generators may be redundant * even so they are homogeneous. */ update_basis_f4(ps, bs, bht, st, st->ngens); /* let's start the f4 rounds, we are done when no more spairs * are left in the pairset */ if (st->info_level > 1) { printf("Learning phase with prime p = %d\n", fc); printf("\ndeg sel pairs mat density \ new data time(rd)\n"); printf("-------------------------------------------------\ ----------------------------------------\n"); } for (round = 1; ps->ld > 0; ++round) { rrt0 = realtime(); st->max_bht_size = st->max_bht_size > bht->esz ? st->max_bht_size : bht->esz; st->current_rd = round; /* preprocess data for next reduction round */ select_spairs_by_minimal_degree(mat, bs, st); symbolic_preprocessing(mat, bs, st); convert_hashes_to_columns(mat, st, sht); sort_matrix_rows_decreasing(mat->rr, mat->nru); sort_matrix_rows_increasing(mat->tr, mat->nrl); /* linear algebra, depending on choice, see set_function_pointers() */ trace_linear_algebra(trace, mat, bs, st); /* columns indices are mapped back to exponent hashes */ if (mat->np > 0) { convert_sparse_matrix_rows_to_basis_elements( -1, mat, bs, bht, sht, st); } clean_hash_table(sht); /* add lead monomials to trace, stores hashes in basis hash * table which is used in all upcoming F4 runs */ if (mat->np > 0) { add_lms_to_trace(trace, bs, mat->np); trace->ltd++; } /* all rows in mat are now polynomials in the basis, * so we do not need the rows anymore */ clear_matrix(mat); /* check redundancy only if input is not homogeneous */ update_basis_f4(ps, bs, bht, st, mat->np); /* if we found a constant we are done, so remove all remaining pairs */ if (bs->constant == 1) { ps->ld = 0; } rrt1 = realtime(); if (st->info_level > 1) { printf("%13.2f sec\n", rrt1-rrt0); } } if (st->info_level > 1) { printf("-------------------------------------------------\ ----------------------------------------\n"); } /* remove possible redudant elements */ final_remove_redundant_elements(bs, st, bht); /* store information in trace */ trace->lml = bs->lml; trace->lmps = (bl_t *)calloc((unsigned long)trace->lml, sizeof(bl_t)); memcpy(trace->lmps, bs->lmps, (unsigned long)trace->lml * sizeof(bl_t)); trace->lm = (sdm_t *)calloc((unsigned long)trace->lml, sizeof(sdm_t)); memcpy(trace->lm, bs->lm, (unsigned long)trace->lml * sizeof(sdm_t)); #if 0 /* eliminate variables if accessible */ if (st->nev > 0) { j = 0; for (i = 0; i < bs->lml; ++i) { if (bht->ev[bs->hm[bs->lmps[i]][OFFSET]][0] == 0) { bs->lm[j] = bs->lm[i]; bs->lmps[j] = bs->lmps[i]; ++j; } } bs->lml = j; } #endif /* reduce final basis */ /* note: bht will become sht, and sht will become NULL, * thus we need pointers */ reduce_basis_no_hash_table_switching(bs, mat, bht, sht, st); /* get basis meta data */ st->size_basis = bs->lml; for (i = 0; i < bs->lml; ++i) { st->nterms_basis += (int64_t)bs->hm[bs->lmps[i]][LENGTH]; } /* timings */ ct1 = cputime(); rt1 = realtime(); st->f4_ctime = ct1 - ct0; st->f4_rtime = rt1 - rt0; get_and_print_final_statistics(stderr, st, bs); /* free and clean up * note: we keep the basis hash table bht for all upcoming runs. * this also means that we do not remove the shared data */ free(hcm); if (sht != NULL) { free_hash_table(&sht); } if (ps != NULL) { free_pairset(&ps); } /* note that all rows kept from mat during the overall computation are * basis elements and thus we do not need to free the rows itself, but * just the matrix structure */ free(mat); /* fix size of trace data */ trace->td = realloc(trace->td, (unsigned long)trace->ltd * sizeof(td_t)); /* Note that we have to add also the numbers of the application counters since * for the interreduction of the matrices we use also during the learning phase * the reduction function which adds to the application counter (since we do not * use any tracing for the interreduction at all). * The application counters will be reset at the start of each application phase, * so we are not counting too many operations in the application runs. */ gst->trace_nr_add = st->trace_nr_add + st->application_nr_add; gst->trace_nr_mult = st->trace_nr_mult + st->application_nr_mult; gst->trace_nr_red = st->trace_nr_red + st->application_nr_red; free(st); return bs; } bs_t *f4sat_trace_learning_phase_1( trace_t *trace, /* trace of the F4sat Algorithm */ ht_t * tht, /* trace hash table for multipliers */ const bs_t * const ggb, /* global basis */ const bs_t * const gsat, /* global saturation element */ ht_t **gbhtp, /* global basis hash table, generated * in this run, used in upcoming runs */ md_t *gst, /* global statistics */ const int32_t fc /* characteristic of field */ ) { /* timings */ double ct = cputime(); double rt = realtime(); double rrt, crt; /* for one round only */ int32_t round, i, j; /* current quotient basis up to max lm degree in intermediate basis */ hm_t *qb = NULL; len_t next_deg = 0; /* global saturation data */ len_t sat_test = 0; deg_t sat_deg = 0; /* int sat_done = 0; */ /* hashes-to-columns maps for multipliers in saturation step */ hi_t *hcmm = (hi_t *)malloc(sizeof(hi_t)); /* matrix holding sparse information generated * during symbolic preprocessing */ mat_t *mat = (mat_t *)calloc(1, sizeof(mat_t)); /* set routines corresponding to prime size */ reset_trace_function_pointers(fc); ps_t * ps = initialize_pairset(); /* copy global data as input */ md_t *st = copy_meta_data(gst, fc); bs_t *bs = copy_basis_mod_p(ggb, st); bs_t *sat = copy_basis_mod_p(gsat, st); ht_t *bht = bs->ht; /* hashes-to-columns map, initialized with length 1, is reallocated * in each call when generating matrices for linear algebra */ st->hcm = (hi_t *)malloc(sizeof(hi_t)); st->ps = ps; /* initialize multiplier of first element in sat to be the hash of * the all-zeroes exponent vector. */ exp_t zero[bht->evl];; memset(zero, 0, (unsigned long)(bht->evl) * sizeof(exp_t)); sat->hm[0][MULT] = insert_in_hash_table(zero, bht); sat->ld = 1; next_deg = 2*bht->ev[sat->hm[0][OFFSET]][DEG]; /* normalize the copied basis */ normalize_initial_basis(bs, fc); /* initialize specialized hash tables */ ht_t *sht = initialize_secondary_hash_table(bht, st); st->ht = sht; st->max_gb_degree = INT32_MAX; /* elements of kernel in saturation step, to be added to basis bs */ bs_t *kernel = initialize_basis(st); /* reset bs->ld for first update process */ bs->ld = 0; /* move input generators to basis and generate first spairs. * always check redundancy since input generators may be redundant * even so they are homogeneous. */ update_basis_f4(ps, bs, bht, st, st->ngens); /* let's start the f4 rounds, we are done when no more spairs * are left in the pairset */ print_round_information_header(stdout, st); round = 1; end_sat_step: for (; ps->ld > 0; ++round) { rrt = realtime(); crt = cputime(); st->max_bht_size = st->max_bht_size > bht->esz ? st->max_bht_size : bht->esz; st->current_rd = round; /* preprocess data for next reduction round */ select_spairs_by_minimal_degree(mat, bs, st); symbolic_preprocessing(mat, bs, st); convert_hashes_to_columns(mat, st, sht); sort_matrix_rows_decreasing(mat->rr, mat->nru); sort_matrix_rows_increasing(mat->tr, mat->nrl); /* linear algebra, depending on choice, see set_function_pointers() */ probabilistic_sparse_linear_algebra_ff_32(mat, bs, bs, st); /* columns indices are mapped back to exponent hashes */ if (mat->np > 0) { convert_sparse_matrix_rows_to_basis_elements( -1, mat, bs, bht, sht, st); sat_test++; } /* all rows in mat are now polynomials in the basis, * so we do not need the rows anymore */ clear_matrix(mat); /* check redundancy only if input is not homogeneous */ update_basis_f4(ps, bs, bht, st, mat->np); if (bs->constant == 1) { printf("basis is constant\n"); ps->ld = 0; break; } clean_hash_table(sht); print_round_timings(stdout, st, rrt, crt); /* saturation step starts here */ if ((bs->mltdeg >= sat->hm[0][DEG] && sat_test != 0) || ps->ld == 0) { /* if (bs->mltdeg - next_deg == 0 || ps->ld == 0) { */ /* if (sat_done == 0 && (sat_test % 3 == 0 || ps->ld == 0)) { */ if (st->nr_kernel_elts > 0 && ps->ld == 0 && is_zero_dimensional(bs, bht) && is_already_saturated( bs, sat, mat, &bht, &sht, st)) { /* sat_done = 1; */ goto end_sat_step; } /* check for new elements to be tested for adding saturation * information to the intermediate basis */ if (ps->ld != 0) { sat_deg = 2*bs->mltdeg/3; } else { sat_deg = bs->mltdeg; } len_t bld = bs->ld; for (deg_t ii = next_deg; ii < sat_deg; ++ii) { rrt = realtime(); crt = cputime(); /* printf("sat->deg %u\n", sat_deg); */ update_multipliers(&qb, &bht, &sht, sat, st, bs, ii); /* check for monomial multiples of elements from saturation list */ select_saturation(sat, mat, st, sht, bht); symbolic_preprocessing(mat, bs, st); /* It may happen that there is no reducer at all for the * saturation elements, then nothing has to be done. */ if (mat->nru > 0) { if (st->info_level > 1) { /* printf("kernel computation "); */ printf("%3u compute kernel", sat_deg); } convert_hashes_to_columns_sat(mat, sat, st, sht); convert_multipliers_to_columns(&hcmm, sat, st, bht); sort_matrix_rows_decreasing(mat->rr, mat->nru); compute_kernel_sat_ff_32(sat, mat, kernel, bs, st); if (st->info_level > 1) { printf("%56d new kernel elements", kernel->ld); fflush(stdout); } if (kernel->ld > 0) { if (st->info_level > 1) { printf("\n "); } clear_matrix(mat); /* interreduce kernel */ copy_kernel_to_matrix(mat, kernel, sat->ld); /* linear algebra, depending on choice, see set_function_pointers() */ probabilistic_sparse_linear_algebra_ff_32(mat, kernel, kernel, st); /* linear_algebra(mat, kernel, st); */ /* columns indices are mapped back to exponent hashes */ if (mat->np > 0) { /* use the correct hcmm for kernel elements! */ hi_t *tmp = st->hcm; st->hcm = hcmm; convert_sparse_matrix_rows_to_basis_elements_use_sht( -1, mat, bs, bht, st); st->hcm = tmp; /* add_minimal_lmh_to_trace(trace, bs); */ trace->ts[trace->lts].deg = ii; trace->ts[trace->lts].f4rd = round; trace->lts++; if (trace->lts == trace->sts) { trace->sts *= 2; trace->ts = realloc(trace->ts, (unsigned long)trace->sts * sizeof(ts_t)); memset(trace->ts+trace->sts/2, 0, (unsigned long)trace->sts/2 * sizeof(ts_t)); } } st->nr_kernel_elts += kernel->ld; sat_test = 0; free_kernel_coefficients(kernel); update_basis_f4(ps, bs, bht, st, mat->np); kernel->ld = 0; if (st->info_level > 1) { printf(" "); } } /* all rows in mat are now polynomials in the basis, * so we do not need the rows anymore */ convert_columns_to_hashes(sat, st, hcmm); for (i = 0; i < sat->ld; ++i) { bht->hd[hcmm[i]].idx = 0; } } clear_matrix(mat); /* move hashes for sat entries from sht back to bht */ for (i = 0; i < sat->ld; ++i) { if (sat->hm[i] != NULL) { while (bht->esz - bht->eld < sat->hm[i][LENGTH]) { enlarge_hash_table(bht); } for (j = OFFSET; j < sat->hm[i][LENGTH]+OFFSET; ++j) { sat->hm[i][j] = insert_in_hash_table( sht->ev[sat->hm[i][j]], bht); } deg_t deg = bht->hd[sat->hm[i][OFFSET]].deg; if (st->nev > 0) { const len_t len = sat->hm[i][LENGTH]+OFFSET; for (j = OFFSET+1; j < len; ++j) { if (deg < bht->hd[sat->hm[i][j]].deg) { deg = bht->hd[sat->hm[i][j]].deg; } } } sat->hm[i][DEG] = deg; } } clean_hash_table(sht); print_sat_round_timings(stdout, st, rrt, crt); if (bld != bs->ld) { next_deg = ii; round++; goto end_sat_step; } } next_deg = sat_deg; } } print_round_information_footer(stdout, st); /* remove possible redudant elements */ final_remove_redundant_elements(bs, st, bht); /* store leading ideal hashes in trace */ trace->lml = bs->lml; trace->lmh = (hm_t *)calloc((unsigned long)trace->lml, sizeof(hm_t)); for (i = 0; i < bs->lml; ++i) { trace->lmh[i] = bs->hm[bs->lmps[i]][OFFSET]; } /* reduce final basis */ /* note: bht will become sht, and sht will become NULL, * thus we need pointers */ if (st->reduce_gb == 1) { reduce_basis(bs, mat, st); } /* printf("basis has %u elements.\n", bs->lml); * * for (i = 0; i < bs->lml; ++i) { * for (j = 0; j < bht->nv; ++j) { * printf("%u ", bht->ev[bs->hm[bs->lmps[i]][OFFSET]][j]); * } * printf("\n"); * } */ /* get basis meta data */ st->size_basis = bs->lml; for (i = 0; i < bs->lml; ++i) { st->nterms_basis += (int64_t)bs->hm[bs->lmps[i]][LENGTH]; } /* timings */ st->f4_rtime = realtime() - rt; st->f4_ctime = cputime() - ct; get_and_print_final_statistics(stderr, st, bs); /* free and clean up * note: we keep the basis hash table bht for all upcoming runs. * this also means that we do not remove the shared data */ free(hcmm); free(qb); *gbhtp = bht; /* if (sht != NULL) { free_hash_table(&sht); } if (ps != NULL) { free_pairset(&ps); } */ free_basis_without_hash_table(&sat); free_basis(&kernel); /* note that all rows kept from mat during the overall computation are * basis elements and thus we do not need to free the rows itself, but * just the matrix structure */ free(mat); /* fix size of trace saturation data */ trace->ts = realloc(trace->ts, (unsigned long)trace->lts * sizeof(ts_t)); /* Note that we have to add also the numbers of the application counters since * for the interreduction of the matrices we use also during the learning phase * the reduction function which adds to the application counter (since we do not * use any tracing for the interreduction at all). * The application counters will be reset at the start of each application phase, * so we are not counting too many operations in the application runs. */ gst->trace_nr_add = st->trace_nr_add + st->application_nr_add; gst->trace_nr_mult = st->trace_nr_mult + st->application_nr_mult; gst->trace_nr_red = st->trace_nr_red + st->application_nr_red; free_meta_data(&st); return bs; } bs_t *f4sat_trace_learning_phase_2( trace_t *trace, /* trace of the F4sat Algorithm */ ht_t * tht, /* trace hash table for multipliers */ const bs_t * const ggb, /* global basis */ const bs_t * const gsat, /* global saturation element */ ht_t **gbhtp, /* global basis hash table, generated * in this run, used in upcoming runs */ md_t *gst, /* global statistics */ const int32_t fc /* characteristic of field */ ) { /* timings */ double ct = cputime(); double rt = realtime(); double rrt, crt; /* for one round only */ int32_t round, i, j; /* current quotient basis up to max lm degree in intermediate basis */ hm_t *qb = NULL; len_t next_deg = 0; /* int sat_done = 0; */ /* hashes-to-columns maps for multipliers in saturation step */ hi_t *hcmm = (hi_t *)malloc(sizeof(hi_t)); /* matrix holding sparse information generated * during symbolic preprocessing */ mat_t *mat = (mat_t *)calloc(1, sizeof(mat_t)); ps_t * ps = initialize_pairset(); /* copy global data as input */ md_t *st = copy_meta_data(gst, fc); bs_t *bs = copy_basis_mod_p(ggb, st); bs_t *sat = copy_basis_mod_p(gsat, st); ht_t *bht = bs->ht; st->trace_level = LEARN_TRACER; /* set routines corresponding to prime size */ reset_function_pointers(fc, st->laopt); int ts_ctr = 0; /* hashes-to-columns map, initialized with length 1, is reallocated * in each call when generating matrices for linear algebra */ st->hcm = (hi_t *)malloc(sizeof(hi_t)); st->ps = ps; /* initialize multiplier of first element in sat to be the hash of * the all-zeroes exponent vector. */ exp_t zero[bht->evl];; memset(zero, 0, (unsigned long)(bht->evl) * sizeof(exp_t)); sat->hm[0][MULT] = insert_in_hash_table(zero, bht); sat->ld = 1; next_deg = 2*bht->ev[sat->hm[0][OFFSET]][DEG]; /* normalize the copied basis */ normalize_initial_basis(bs, fc); /* initialize specialized hash tables */ ht_t *sht = initialize_secondary_hash_table(bht, st); st->ht = sht; st->max_gb_degree = INT32_MAX; /* elements of kernel in saturation step, to be added to basis bs */ bs_t *kernel = initialize_basis(st); /* reset bs->ld for first update process */ bs->ld = 0; /* move input generators to basis and generate first spairs. * always check redundancy since input generators may be redundant * even so they are homogeneous. */ update_basis_f4(ps, bs, bht, st, st->ngens); /* let's start the f4 rounds, we are done when no more spairs * are left in the pairset */ print_round_information_header(stdout, st); round = 1; for (; ps->ld > 0; ++round) { /* check if we have already computed the * full basis via tracer information */ if (minimal_traced_lm_is_equal(trace->lmh, trace->lml, bs) == 1) { ps->ld = 0; break; } rrt = realtime(); crt = cputime(); st->max_bht_size = st->max_bht_size > bht->esz ? st->max_bht_size : bht->esz; st->current_rd = round; /* preprocess data for next reduction round */ select_spairs_by_minimal_degree(mat, bs, st); symbolic_preprocessing(mat, bs, st); convert_hashes_to_columns(mat, st, sht); sort_matrix_rows_decreasing(mat->rr, mat->nru); sort_matrix_rows_increasing(mat->tr, mat->nrl); /* linear algebra, depending on choice, see set_function_pointers() */ linear_algebra(mat, bs, bs, st); /* columns indices are mapped back to exponent hashes */ if (mat->np > 0) { convert_sparse_matrix_rows_to_basis_elements( -1, mat, bs, bht, sht, st); } clean_hash_table(sht); /* add lead monomials to trace, stores hashes in basis hash * table which is used in all upcoming F4 runs */ if (mat->np > 0) { add_lms_to_trace(trace, bs, mat->np); trace->ltd++; } /* all rows in mat are now polynomials in the basis, * so we do not need the rows anymore */ clear_matrix(mat); /* check redundancy only if input is not homogeneous */ update_basis_f4(ps, bs, bht, st, mat->np); /* if we found a constant we are done, so remove all remaining pairs */ if (bs->constant == 1) { printf("basis is constant\n"); ps->ld = 0; break; } clean_hash_table(sht); print_round_timings(stdout, st, rrt, crt); /* saturation step starts here */ /* if (ts_ctr < trace->lts && minimal_traced_lm_is_equal(trace->ts[ts_ctr].lmh, trace->ts[ts_ctr].lml, bs) == 1) { */ if (ts_ctr < trace->lts && trace->ts[ts_ctr].f4rd == round) { next_deg = trace->ts[ts_ctr].deg; rrt = realtime(); crt = cputime(); /* printf("sat->deg %u\n", sat_deg); */ update_multipliers(&qb, &bht, &sht, sat, st, bs, next_deg); /* check for monomial multiples of elements from saturation list */ select_saturation(sat, mat, st, sht, bht); symbolic_preprocessing(mat, bs, st); /* It may happen that there is no reducer at all for the * saturation elements, then nothing has to be done. */ if (mat->nru > 0) { if (st->info_level > 1) { /* printf("kernel computation "); */ printf("%3u compute kernel", next_deg); } convert_hashes_to_columns_sat(mat, sat, st, sht); convert_multipliers_to_columns(&hcmm, sat, st, bht); sort_matrix_rows_decreasing(mat->rr, mat->nru); construct_saturation_trace(trace, ts_ctr, mat); compute_kernel_sat_ff_32(sat, mat, kernel, bs, st); if (st->info_level > 1) { printf("%56d new kernel elements", kernel->ld); fflush(stdout); printf("\n "); } clear_matrix(mat); /* interreduce kernel */ copy_kernel_to_matrix(mat, kernel, sat->ld); /* linear algebra, depending on choice, see set_function_pointers() */ probabilistic_sparse_linear_algebra_ff_32(mat, kernel, kernel, st); /* linear_algebra(mat, kernel, st); */ /* columns indices are mapped back to exponent hashes */ if (mat->np > 0) { /* use the correct hcmm for kernel elements! */ hi_t *tmp = st->hcm; st->hcm = hcmm; convert_sparse_matrix_rows_to_basis_elements_use_sht( -1, mat, bs, bht, st); st->hcm = tmp; } /* track round in which kernel computation is not trivial */ if (trace->rld == trace->rsz) { trace->rsz *= 2; trace->rd = realloc( trace->rd, (unsigned long)trace->rsz * sizeof(len_t)); } /* in the application phase round counting * starts at 0, so that's OK */ trace->rd[trace->rld++] = trace->ltd-1; st->nr_kernel_elts += kernel->ld; free_kernel_coefficients(kernel); update_basis_f4(ps, bs, bht, st, mat->np); kernel->ld = 0; if (st->info_level > 1) { printf(" "); } /* columns indices are mapped back to exponent hashes */ /* return_normal_forms_to_basis( * mat, tbr, bht, sht, hcm, st); */ /* all rows in mat are now polynomials in the basis, * so we do not need the rows anymore */ convert_columns_to_hashes(sat, st, hcmm); for (i = 0; i < sat->ld; ++i) { bht->hd[hcmm[i]].idx = 0; } } clear_matrix(mat); /* move hashes for sat entries from sht back to bht */ for (i = 0; i < sat->ld; ++i) { if (sat->hm[i] != NULL) { while (bht->esz - bht->eld < sat->hm[i][LENGTH]) { enlarge_hash_table(bht); } for (j = OFFSET; j < sat->hm[i][LENGTH]+OFFSET; ++j) { sat->hm[i][j] = insert_in_hash_table( sht->ev[sat->hm[i][j]], bht); } deg_t deg = bht->hd[sat->hm[i][OFFSET]].deg; if (st->nev > 0) { const len_t len = sat->hm[i][LENGTH]+OFFSET; for (j = OFFSET+1; j < len; ++j) { if (deg < bht->hd[sat->hm[i][j]].deg) { deg = bht->hd[sat->hm[i][j]].deg; } } } sat->hm[i][DEG] = deg; } } clean_hash_table(sht); print_sat_round_timings(stdout, st, rrt, crt); ts_ctr++; } } print_round_information_footer(stdout, st); /* remove possible redudant elements */ final_remove_redundant_elements(bs, st, bht); /* store information in trace */ trace->lml = bs->lml; trace->lmps = (bl_t *)calloc((unsigned long)trace->lml, sizeof(bl_t)); memcpy(trace->lmps, bs->lmps, (unsigned long)trace->lml * sizeof(bl_t)); trace->lm = (sdm_t *)calloc((unsigned long)trace->lml, sizeof(sdm_t)); memcpy(trace->lm, bs->lm, (unsigned long)trace->lml * sizeof(sdm_t)); /* reduce final basis */ /* note: bht will become sht, and sht will become NULL, * thus we need pointers */ if (st->reduce_gb == 1) { reduce_basis(bs, mat, st); } /* printf("basis has %u elements.\n", bs->lml); * * for (i = 0; i < bs->lml; ++i) { * for (j = 0; j < bht->nv; ++j) { * printf("%u ", bht->ev[bs->hm[bs->lmps[i]][OFFSET]][j]); * } * printf("\n"); * } */ /* get basis meta data */ st->size_basis = bs->lml; for (i = 0; i < bs->lml; ++i) { st->nterms_basis += (int64_t)bs->hm[bs->lmps[i]][LENGTH]; } /* timings */ st->f4_rtime = realtime() - rt; st->f4_ctime = cputime() - ct; get_and_print_final_statistics(stderr, st, bs); /* free and clean up * note: we keep the basis hash table bht for all upcoming runs. * this also means that we do not remove the shared data */ free(hcmm); free(qb); *gbhtp = bht; /* if (sht != NULL) { free_hash_table(&sht); } if (ps != NULL) { free_pairset(&ps); } */ free_basis_without_hash_table(&sat); free_basis(&kernel); /* note that all rows kept from mat during the overall computation are * basis elements and thus we do not need to free the rows itself, but * just the matrix structure */ free(mat); /* fix size of trace data */ trace->td = realloc(trace->td, (unsigned long)trace->ltd * sizeof(td_t)); /* Note that we have to add also the numbers of the application counters since * for the interreduction of the matrices we use also during the learning phase * the reduction function which adds to the application counter (since we do not * use any tracing for the interreduction at all). * The application counters will be reset at the start of each application phase, * so we are not counting too many operations in the application runs. */ gst->trace_nr_add = st->trace_nr_add + st->application_nr_add; gst->trace_nr_mult = st->trace_nr_mult + st->application_nr_mult; gst->trace_nr_red = st->trace_nr_red + st->application_nr_red; free_meta_data(&st); return bs; } int64_t f4_trace_julia( /* return values */ int32_t *bld, /* basis load */ int32_t **blen, /* length of each poly in basis */ int32_t **bexp, /* basis exponent vectors */ void **bcf, /* coefficients of basis elements */ /* input values */ const int32_t *lens, const int32_t *exps, const void *cfs, uint32_t field_char, int32_t mon_order, int32_t elim_block_len, int32_t nr_vars, int32_t nr_gens, int32_t ht_size, int32_t nr_threads, int32_t max_nr_pairs, int32_t reset_ht, int32_t la_option, int32_t reduce_gb, uint32_t prime_start, int32_t nr_primes, int32_t pbm_file, int32_t info_level ) { /* only for computations over the rationals */ if (field_char != 0) { fprintf(stderr, "Tracer only for computations over Q. Call\n"); fprintf(stderr, "standard F4 Algorithm for computations over\n"); fprintf(stderr, "finite fields.\n"); return 1; } len_t i; /* ps is only needed for storing meta data */ ps_t *ps = initialize_pairset(); /* lucky primes */ primes_t *lp = (primes_t *)calloc(1, sizeof(primes_t)); /* initialize stuff */ md_t *st = allocate_meta_data(); int *invalid_gens = NULL; int32_t use_signatures = 0; int32_t nr_nf = 0; int res = validate_input_data(&invalid_gens, cfs, lens, &field_char, &mon_order, &elim_block_len, &nr_vars, &nr_gens, &nr_nf, &ht_size, &nr_threads, &max_nr_pairs, &reset_ht, &la_option, &use_signatures, &reduce_gb, &info_level); /* all data is corrupt */ if (res == -1) { free(invalid_gens); return res; } /* checks and set all meta data. if a nonzero value is returned then * some of the input data is corrupted. */ if (check_and_set_meta_data_trace(st, lens, exps, cfs, invalid_gens, field_char, mon_order, elim_block_len, nr_vars, nr_gens, nr_nf, ht_size, nr_threads, max_nr_pairs, reset_ht, la_option, use_signatures, reduce_gb, prime_start, nr_primes, pbm_file, info_level)) { return 0; } /******************* * initialize basis *******************/ bs_t *bs_qq = initialize_basis(st); /* initialize basis hash table, update hash table, symbolic hash table */ ht_t *bht = initialize_basis_hash_table(st); /* hash table to store the hashes of the multiples of * the basis elements stored in the trace */ ht_t *tht = initialize_secondary_hash_table(bht, st); /* read in ideal, move coefficients to integers */ import_input_data(bs_qq, st, 0, st->ngens_input, lens, exps, cfs, invalid_gens); free(invalid_gens); invalid_gens = NULL; print_initial_statistics(stderr, st); /* for faster divisibility checks, needs to be done after we have * read some input data for applying heuristics */ calculate_divmask(bht); /* sort initial elements, smallest lead term first */ sort_r(bs_qq->hm, (unsigned long)bs_qq->ld, sizeof(hm_t *), initial_input_cmp, bht); remove_content_of_initial_basis(bs_qq); /* generate lucky prime numbers */ generate_lucky_primes(lp, bs_qq, st->prime_start, st->nprimes); /* generate array to store modular bases */ bs_t **bs = (bs_t **)calloc((unsigned long)st->nprimes, sizeof(bs_t *)); /* initialize tracer */ trace_t *trace = initialize_trace(bs_qq, st); /* learning phase */ bs[0] = f4_trace_learning_phase(trace, tht, bs_qq, bht, st, lp->p[0]); /* tracing phase */ #pragma omp parallel for num_threads(st->nthrds) \ private(i) schedule(dynamic) for (i = 1; i < st->nprimes; ++i) { bs[i] = f4_trace_application_phase( trace, tht, bs_qq, bht, st, lp->p[i]); } /* reconstruction phase */ /* testing phase */ /* free and clean up */ free_trace(&trace); free_shared_hash_data(bht); free_hash_table(&bht); free_pairset(&ps); for (i = 0; i < st->nprimes; ++i) { free_basis(&(bs[i])); } free(bs); free_lucky_primes(&lp); free(st); return 0; } /* modular f4 call for usual multi-modular f4, no tracing */ bs_t *modular_f4( const bs_t * const ggb, /* global basis */ ht_t * gbht, /* global basis hash table, shared */ md_t *gst, /* global statistics */ const uint32_t fc /* characteristic of field */ ) { /* timings */ double ct0, ct1, rt0, rt1; double rrt0, rrt1; /* for one round only */ ct0 = cputime(); rt0 = realtime(); int32_t round, i; /* hashes-to-columns map, initialized with length 1, is reallocated * in each call when generating matrices for linear algebra */ hi_t *hcm = (hi_t *)malloc(sizeof(hi_t)); /* set routines corresponding to prime size */ reset_function_pointers(fc, gst->laopt); /* matrix holding sparse information generated * during symbolic preprocessing */ mat_t *mat = (mat_t *)calloc(1, sizeof(mat_t)); ps_t * ps = initialize_pairset(); /* copy global data as input */ md_t *st = copy_meta_data(gst, fc); bs_t *bs = copy_basis_mod_p(ggb, st); ht_t *bht = gbht; /* normalize the copied basis */ normalize_initial_basis(bs, fc); /* initialize specialized hash table */ ht_t *sht = initialize_secondary_hash_table(bht, st); /* reset bs->ld for first update process */ bs->ld = 0; /* move input generators to basis and generate first spairs. * always check redundancy since input generators may be redundant * even so they are homogeneous. */ update_basis_f4(ps, bs, bht, st, st->ngens); /* let's start the f4 rounds, we are done when no more spairs * are left in the pairset */ if (st->info_level > 1) { printf("\ndeg sel pairs mat density \ new data time(rd)\n"); printf("-------------------------------------------------\ ----------------------------------------\n"); } for (round = 1; ps->ld > 0; ++round) { rrt0 = realtime(); st->max_bht_size = st->max_bht_size > bht->esz ? st->max_bht_size : bht->esz; st->current_rd = round; /* preprocess data for next reduction round */ select_spairs_by_minimal_degree(mat, bs, st); symbolic_preprocessing(mat, bs, st); convert_hashes_to_columns(mat, st, sht); sort_matrix_rows_decreasing(mat->rr, mat->nru); sort_matrix_rows_increasing(mat->tr, mat->nrl); /* print pbm files of the matrices */ if (st->gen_pbm_file != 0) { write_pbm_file(mat, st); } /* linear algebra, depending on choice, see set_function_pointers() */ linear_algebra(mat, bs, bs, st); /* columns indices are mapped back to exponent hashes */ if (mat->np > 0) { convert_sparse_matrix_rows_to_basis_elements( -1, mat, bs, bht, sht, st); } clean_hash_table(sht); /* all rows in mat are now polynomials in the basis, * so we do not need the rows anymore */ clear_matrix(mat); /* check redundancy only if input is not homogeneous */ update_basis_f4(ps, bs, bht, st, mat->np); rrt1 = realtime(); if (st->info_level > 1) { printf("%13.2f sec\n", rrt1-rrt0); } } if (st->info_level > 1) { printf("-------------------------------------------------\ ----------------------------------------\n"); } /* remove possible redudant elements */ final_remove_redundant_elements(bs, st, bht); #if 0 /* eliminate variables if accessible */ if (st->nev > 0) { j = 0; for (i = 0; i < bs->lml; ++i) { if (bht->ev[bs->hm[bs->lmps[i]][OFFSET]][0] == 0) { bs->lm[j] = bs->lm[i]; bs->lmps[j] = bs->lmps[i]; ++j; } } bs->lml = j; } #endif /* reduce final basis? */ if (st->reduce_gb == 1) { reduce_basis_no_hash_table_switching( bs, mat, bht, sht, st); /* reduce_basis_(bs, mat, &hcm, &bht, &sht, st); */ } /* timings */ ct1 = cputime(); rt1 = realtime(); st->f4_ctime = ct1 - ct0; st->f4_rtime = rt1 - rt0; /* get basis meta data */ st->size_basis = bs->lml; for (i = 0; i < bs->lml; ++i) { st->nterms_basis += (int64_t)bs->hm[bs->lmps[i]][LENGTH]; } get_and_print_final_statistics(stderr, st, bs); /* free and clean up */ free(hcm); if (sht != NULL) { free_hash_table(&sht); } if (ps != NULL) { free_pairset(&ps); } /* note that all rows kept from mat during the overall computation are * basis elements and thus we do not need to free the rows itself, but * just the matrix structure */ free(mat); free(st); return bs; } msolve-0.6.5/src/neogb/modular.h000066400000000000000000000146711456710632100165420ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef GB_TRACE_H #define GB_TRACE_H #include "data.h" trace_t *initialize_trace( const bs_t * const bs, const md_t * const md ); void free_trace( trace_t **trp ); void free_lucky_primes( primes_t **lpp ); static inline int is_lucky_prime_ui( const uint32_t prime, const bs_t * const bs ) { len_t i, j; mpz_t *cf; const len_t bl = bs->ld; for (i = 0; i < bl; ++i) { cf = bs->cf_qq[bs->hm[i][COEFFS]]; for (j = 0; j < bs->hm[i][LENGTH]; ++j) { if (mpz_divisible_ui_p(cf[j], prime) != 0) { return 1; } } } return 0; } static inline int is_lucky_prime( const mpz_t prime, const bs_t * const bs ) { len_t i, j; mpz_t *cf; const len_t bl = bs->ld; for (i = 0; i < bl; ++i) { cf = bs->cf_qq[bs->hm[i][COEFFS]]; for (j = 0; j < bs->hm[i][LENGTH]; ++j) { if (mpz_divisible_p(cf[j], prime) != 0) { return 1; } } } return 0; } void reduce_basis_no_hash_table_switching( bs_t *bs, mat_t *mat, ht_t *bht, ht_t *sht, md_t *st ); static inline void generate_lucky_primes( primes_t *lp, const bs_t * const bs, const uint32_t start, const len_t nr_new_primes ) { len_t i; lp->old = lp->ld; lp->ld += nr_new_primes; lp->p = realloc(lp->p, (unsigned long)(lp->ld) * sizeof(uint32_t)); mpz_t last_prime; mpz_init(last_prime); if (lp->old == 0) { mpz_set_ui(last_prime, start); } else { mpz_set_ui(last_prime, lp->p[lp->old-1]); } mpz_nextprime(last_prime, last_prime); i = lp->old; while (i < lp->ld) { if (is_lucky_prime(last_prime, bs) == 0) { lp->p[i++] = (int32_t)mpz_get_ui(last_prime); } mpz_nextprime(last_prime, last_prime); } mpz_clear(last_prime); } bs_t *f4_trace_learning_phase( trace_t *trace, /* trace of the F4 Algorithm */ ht_t * tht, /* trace hash table for multipliers */ const bs_t * const ggb, /* global basis */ ht_t *gbht, /* global basis hash table, generated * in this run, used in upcoming runs */ md_t *gst, /* global statistics */ const int32_t fc /* characteristic of field */ ); bs_t *f4sat_trace_learning_phase_1( trace_t *trace, /* trace of the F4 Algorithm */ ht_t * tht, /* trace hash table for multipliers */ const bs_t * const ggb, /* global basis */ const bs_t * const gsat, /* global saturation elements */ ht_t **gbhtp, /* global basis hash table, generated * in this run, used in upcoming runs */ md_t *gst, /* global statistics */ const int32_t fc /* characteristic of field */ ); bs_t *f4sat_trace_learning_phase_2( trace_t *trace, /* trace of the F4 Algorithm */ ht_t * tht, /* trace hash table for multipliers */ const bs_t * const ggb, /* global basis */ const bs_t * const gsat, /* global saturation elements */ ht_t **gbhtp, /* global basis hash table, generated * in this run, used in upcoming runs */ md_t *gst, /* global statistics */ const int32_t fc /* characteristic of field */ ); bs_t *f4_trace_application_phase( const trace_t * const trace, /* trace of the F4 Algorithm */ const ht_t * const tht, /* trace hash table for multipliers */ const bs_t * const ggb, /* global basis */ ht_t *lbht, /* local basis hash table, not shared */ md_t *gst, /* global statistics */ const uint32_t fc /* characteristic of field */ ); bs_t *f4sat_trace_application_phase( const trace_t * const trace, /* trace of the F4 Algorithm */ const ht_t * const tht, /* trace hash table for multipliers */ const bs_t * const ggb, /* global basis */ const bs_t * const gsat, /* global saturation elements */ ht_t *lbht, /* local basis hash table, not shared */ md_t *gst, /* global statistics */ const uint32_t fc /* characteristic of field */ ); int64_t f4_trace_julia( int32_t *bld, /* basis load */ int32_t **blen, /* length of each poly in basis */ int32_t **bexp, /* basis exponent vectors */ void **bcf, /* coefficients of basis elements */ const int32_t *lens, const int32_t *exps, const void *cfs, const uint32_t field_char, const int32_t mon_order, const int32_t elim_block_len, const int32_t nr_vars, const int32_t nr_gens, const int32_t ht_size, const int32_t nr_threads, const int32_t max_nr_pairs, const int32_t reset_hash_table, const int32_t la_option, const int32_t reduce_gb, const uint32_t prime_start, const int32_t nr_primes, const int32_t pbm_file, const int32_t info_level ); bs_t *modular_f4( const bs_t * const ggb, /* global basis */ ht_t * gbht, /* global basis hash table, shared */ md_t *gst, /* global statistics */ const uint32_t fc /* characteristic of field */ ); #endif msolve-0.6.5/src/neogb/nf.c000066400000000000000000000145741456710632100154770ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "nf.h" /* 31-bit implementation only at the moment */ void get_normal_form_matrix( const bs_t * const tbr, ht_t *bht, const len_t start, md_t *st, ht_t **shtp, hi_t **hcmp, mat_t **matp ) { /* hi_t *hcm = *hcmp; */ ht_t *sht = *shtp; mat_t*mat = *matp; /* mul is (0,...,0) */ exp_t *mul = (exp_t *)calloc(bht->nv, sizeof(exp_t)); select_tbr(tbr, mul, start, mat, st, sht, bht, NULL); /* mat->nc usually computed inside symbolic preprocessing, * here we have to set it by hand; same holds for mat->nrl */ mat->nrl = mat->nr; mat->nc = sht->eld-1; convert_hashes_to_columns(mat, st, sht); sort_matrix_rows_decreasing(mat->rr, mat->nru); /* *hcmp = hcm; */ *shtp = sht; *matp = mat; } bs_t *core_nf( bs_t *tbr, md_t *md, const exp_t * const mul, bs_t *bs, int32_t *errp ) { double ct = cputime(); double rt = realtime(); ht_t *bht = bs->ht; /* reset to exact linear algebra for normal form computation */ md->laopt = 2; set_function_pointers(md); /* matrix holding sparse information generated * during symbolic preprocessing */ mat_t *mat = (mat_t *)calloc(1, sizeof(mat_t)); md->hcm = (hi_t *)malloc(sizeof(hi_t)); md->ht = initialize_secondary_hash_table(bht, md); md->nf = 1; select_tbr(tbr, mul, 0, mat, md, md->ht, bht, NULL); symbolic_preprocessing(mat, bs, md); convert_hashes_to_columns(mat, md, md->ht); sort_matrix_rows_decreasing(mat->rr, mat->nru); /* linear algebra, depending on choice, see set_function_pointers() */ linear_algebra(mat, tbr, bs, md); /* columns indices are mapped back to exponent hashes */ return_normal_forms_to_basis( mat, tbr, bht, md->ht, md->hcm, md); /* all rows in mat are now polynomials in the basis, * so we do not need the rows anymore */ clear_matrix(mat); print_round_timings(stdout, md, rt, ct); print_round_information_footer(stdout, md); /* free and clean up */ free(md->hcm); if (md->ht != NULL) { free_hash_table(&(md->ht)); } /* note that all rows kept from mat during the overall computation are * basis elements and thus we do not need to free the rows itself, but * just the matrix structure */ free(mat); *errp = 0; return tbr; } int64_t export_nf( void *(*mallocp) (size_t), /* return values */ int32_t *nf_ld, /* basis load */ int32_t **nf_len, /* length of each poly in basis */ int32_t **nf_exp, /* basis exponent vectors */ void **nf_cf, /* coefficients of basis elements */ /* input values */ const int32_t nr_tbr_gens, const int32_t *tbr_lens, const int32_t *tbr_exps, const void *tbr_cfs, const int32_t nr_bs_gens, const int32_t *bs_lens, const int32_t *bs_exps, const void *bs_cfs, const uint32_t field_char, const int32_t mon_order, const int32_t elim_block_len, const int32_t nr_vars, const int32_t bs_is_gb, const int32_t nr_threads, const int32_t info_level ) { /* timings */ double ct = cputime(); double rt = realtime(); /* data structures for basis, hash table and statistics */ bs_t *bs = NULL; bs_t *tbr = NULL; md_t *md = NULL; ht_t *bht = NULL; int32_t err = 0; int success = 0; /* get polys w.r.t. which we reduce */ success = initialize_gba_input_data(&bs, &bht, &md, bs_lens, bs_exps, bs_cfs, field_char, mon_order, elim_block_len, nr_vars, nr_bs_gens, 0, 17, nr_threads, 0, 0, 44, 0, 1, 0, info_level); /* all input generators are invalid */ if (success == -1) { return_zero(nf_ld, nf_len, nf_exp, nf_cf, nr_vars, field_char, mallocp); return 1; } if (success == 0) { printf("Bad input data, stopped computation.\n"); exit(1); } if (bs_is_gb == 1) { for (len_t k = 0; k < bs->ld; ++k) { bs->lmps[k] = k; bs->lm[k] = bht->hd[bs->hm[k][OFFSET]].sdm; bs->lml = bs->ld; } } else { /* compute a gb for initial generators */ bs = core_gba(bs, md, &err, md->fc); if (err) { printf("Problem with F4, stopped computation.\n"); exit(1); } } /* initialize data for elements to be reduced, * NOTE: Don't initialize BEFORE running core_f4, bht may * change, so hash values of tbr may become wrong. */ tbr = initialize_basis(md); tbr->ht = bht; import_input_data(tbr, md, 0, nr_tbr_gens, tbr_lens, tbr_exps, (void *)tbr_cfs, NULL); tbr->ld = tbr->lml = nr_tbr_gens; /* generate array for storing multiplier for polynomial * to be reduced by basis */ exp_t *mul = (exp_t *)calloc(bht->evl, sizeof(exp_t)); /* compute normal form of last element in tbr */ tbr = core_nf(tbr, md, mul, bs, &err); if (err) { printf("Problem with normalform, stopped computation.\n"); exit(1); } int64_t nterms = export_results_from_f4(nf_ld, nf_len, nf_exp, nf_cf, mallocp, &tbr, &bht, &md); /* timings */ md->nf_ctime = cputime() - ct; md->nf_rtime = realtime() - rt; get_and_print_final_statistics(stderr, md, tbr); /* free and clean up */ free_shared_hash_data(bht); if (tbr != NULL) { free_basis_without_hash_table(&tbr); } if (bs != NULL) { free_basis(&bs); } free(md); md = NULL; return nterms; } msolve-0.6.5/src/neogb/nf.h000066400000000000000000000037111456710632100154730ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef GB_NF_H #define GB_NF_H #include "data.h" #include "f4.h" void get_normal_form_matrix( const bs_t * const tbr, ht_t * bht, const len_t start, md_t *st, ht_t **shtp, hi_t **hcmp, mat_t **matp ); bs_t *core_nf( bs_t *tbr, md_t *md, const exp_t * const mul, bs_t *bs, int32_t *errp ); int64_t export_nf( void *(*mallocp) (size_t), /* return values */ int32_t *nf_ld, /* basis load */ int32_t **nf_len, /* length of each poly in basis */ int32_t **nf_exp, /* basis exponent vectors */ void **nf_cf, /* coefficients of basis elements */ /* input values */ const int32_t nr_tbr_gens, const int32_t *tbr_lens, const int32_t *tbr_exps, const void *tbr_cfs, const int32_t nr_bs_gens, const int32_t *bs_lens, const int32_t *bs_exps, const void *bs_cfs, const uint32_t field_char, const int32_t mon_order, const int32_t elim_block_len, const int32_t nr_vars, const int32_t bs_is_gb, const int32_t nr_threads, const int32_t info_level ); #endif msolve-0.6.5/src/neogb/order.c000066400000000000000000000451151456710632100162020ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "data.h" /* * IMPLEMENTATIONS OF ORDER FUNCTIONIONALITY INDEPENDENT * OF CHOSEN MONOMIAL ORDER * */ static int matrix_row_cmp_decreasing( const void *a, const void *b ) { hm_t va, vb; /* compare pivot resp. column index */ va = ((hm_t **)a)[0][OFFSET]; vb = ((hm_t **)b)[0][OFFSET]; if (va > vb) { return 1; } if (va < vb) { return -1; } /* same column index => compare density of row */ va = ((hm_t **)a)[0][LENGTH]; vb = ((hm_t **)b)[0][LENGTH]; if (va > vb) { return 1; } if (va < vb) { return -1; } return 0; } static int matrix_row_cmp_increasing( const void *a, const void *b ) { hm_t va, vb; /* compare pivot resp. column index */ va = ((hm_t **)a)[0][OFFSET]; vb = ((hm_t **)b)[0][OFFSET]; if (va > vb) { return -1; } if (va < vb) { return 1; } /* same column index => compare density of row */ va = ((hm_t **)a)[0][LENGTH]; vb = ((hm_t **)b)[0][LENGTH]; if (va > vb) { return -1; } if (va < vb) { return 1; } return 0; } static int matrix_row_mult_cmp_increasing( const void *a, const void *b ) { hm_t va, vb; /* compare pivot resp. column index */ va = ((hm_t **)a)[0][OFFSET]; vb = ((hm_t **)b)[0][OFFSET]; if (va > vb) { return -1; } if (va < vb) { return 1; } /* compare multiplier resp. column index */ va = ((hm_t **)a)[0][MULT]; vb = ((hm_t **)b)[0][MULT]; if (va > vb) { return -1; } if (va < vb) { return 1; } /* same column index => compare density of row */ va = ((hm_t **)a)[0][LENGTH]; vb = ((hm_t **)b)[0][LENGTH]; if (va > vb) { return -1; } if (va < vb) { return 1; } return 0; } static inline void sort_matrix_rows_decreasing( hm_t **rows, const len_t nrows ) { qsort(rows, (unsigned long)nrows, sizeof(hm_t *), &matrix_row_cmp_decreasing); } static inline void sort_matrix_rows_increasing( hm_t **rows, const len_t nrows ) { qsort(rows, (unsigned long)nrows, sizeof(hm_t *), &matrix_row_cmp_increasing); } static inline void sort_matrix_rows_mult_increasing( hm_t **rows, const len_t nrows ) { qsort(rows, (unsigned long)nrows, sizeof(hm_t *), &matrix_row_mult_cmp_increasing); } static int dense_matrix_row_cmp( const void *a, const void *b ) { const cf32_t pa = ((cf32_t **)a)[0][0]; const cf32_t pb = ((cf32_t **)b)[0][0]; return pa-pb; } static inline cf32_t **sort_dense_matrix_rows( cf32_t **dm, const len_t nr ) { qsort(dm, (unsigned long)nr, sizeof(cf32_t *), &dense_matrix_row_cmp); return dm; } /* comparison for spair generators */ static int gens_cmp( const void *a, const void *b ) { const len_t ga = *((len_t *)a); const len_t gb = *((len_t *)b); return (ga - gb); } /* comparison for sparse rows in preparation for generation of pbm files */ static int pbm_cmp( const void *a, const void *b ) { const hm_t ca = *((hm_t *)a); const hm_t cb = *((hm_t *)b); return (ca - cb); } #if 0 static int spair_degree_cmp( const void *a, const void *b, void *htp ) { ht_t *ht = htp; const hi_t la = ((spair_t *)a)->lcm; const hi_t lb = ((spair_t *)b)->lcm; const exp_t ea = ht->hd[la].deg; const exp_t eb = ht->hd[lb].deg; if (ea-eb != 0) { return (ea-eb); } else { const deg_t da = ((spair_t *)a)->deg; const deg_t db = ((spair_t *)b)->deg; return (da - db); } } #endif /* * IMPLEMENTATIONS FOR LEXICOGRAPHICAL ORDER * */ static int initial_input_cmp_lex( const void *a, const void *b, void *htp ) { len_t i; ht_t *ht = htp; const hm_t ha = ((hm_t **)a)[0][OFFSET]; const hm_t hb = ((hm_t **)b)[0][OFFSET]; const exp_t * const ea = ht->ev[ha]; const exp_t * const eb = ht->ev[hb]; /* lexicographical */ const len_t evl = ht->evl; i = 1; while(i < evl-1 && ea[i] == eb[i]) { ++i; } return ea[i] - eb[i]; } static int initial_gens_cmp_lex( const void *a, const void *b, void *htp ) { len_t i; ht_t *ht = htp; const hm_t ha = **(hm_t **)a; const hm_t hb = **(hm_t **)b; const exp_t * const ea = ht->ev[ha]; const exp_t * const eb = ht->ev[hb]; /* lexicographical */ const len_t evl = ht->evl; i = 1; while(i < evl-1 && ea[i] == eb[i]) { ++i; } return ea[i] - eb[i]; } static int monomial_cmp_pivots_lex( const hi_t a, const hi_t b, const ht_t * const ht ) { len_t i; const hd_t ha = ht->hd[a]; const hd_t hb = ht->hd[b]; #if ORDER_COLUMNS /* first known pivots vs. tail terms */ if (ha.idx != hb.idx) { if (ha.idx < hb.idx) { return 1; } else { return -1; } } #endif const exp_t * const ea = ht->ev[a]; const exp_t * const eb = ht->ev[b]; /* lexicographical */ const len_t evl = ht->evl; i = 1; while(i < evl-1 && ea[i] == eb[i]) { ++i; } return eb[i] - ea[i]; } static inline int monomial_cmp_lex( const hi_t a, const hi_t b, const ht_t *ht ) { len_t i; const exp_t * const ea = ht->ev[a]; const exp_t * const eb = ht->ev[b]; const len_t evl = ht->evl; i = 1; while(i < evl-1 && ea[i] == eb[i]) { ++i; } return ea[i] - eb[i]; } static int hcm_cmp_pivots_lex( const void *a, const void *b, void *htp ) { const ht_t *ht = (ht_t *)htp; const hi_t ma = ((hi_t *)a)[0]; const hi_t mb = ((hi_t *)b)[0]; return monomial_cmp_pivots_lex(ma, mb, ht); } /* comparison for s-pairs once their lcms are in the global hash table */ static int spair_cmp_deglex( const void *a, const void *b, void *htp ) { const hi_t la = ((spair_t *)a)->lcm; const hi_t lb = ((spair_t *)b)->lcm; const ht_t *ht = (ht_t *)htp; if (ht->ev[la][DEG] != ht->ev[lb][DEG]) { return (ht->ev[la][DEG] < ht->ev[lb][DEG]) ? -1 : 1; } else { return (int)monomial_cmp(la, lb, ht); } } /* * IMPLEMENTATIONS FOR DEGREE REVERSE LEXICOGRAPHICAL ORDER * */ #if 0 static int initial_input_cmp_drl_reverse( const void *a, const void *b, void *htp ) { len_t i; ht_t *ht = htp; const hm_t ha = ((hm_t **)a)[0][OFFSET]; const hm_t hb = ((hm_t **)b)[0][OFFSET]; const exp_t * const ea = ht->ev[ha]; const exp_t * const eb = ht->ev[hb]; /* DRL */ if (ea[DEG] > eb[DEG]) { return 1; } else { if (ea[DEG] != eb[DEG]) { return -1; } } /* note: reverse lexicographical */ i = ht->evl-1; while (i > 1 && ea[i] == eb[i]) { --i; } return eb[i] - ea[i]; } #endif static int initial_input_cmp_drl( const void *a, const void *b, void *htp ) { len_t i; ht_t *ht = htp; const hm_t ha = ((hm_t **)a)[0][OFFSET]; const hm_t hb = ((hm_t **)b)[0][OFFSET]; const exp_t * const ea = ht->ev[ha]; const exp_t * const eb = ht->ev[hb]; /* DRL */ if (ea[DEG] < eb[DEG]) { return -1; } else { if (ea[DEG] != eb[DEG]) { return 1; } } /* note: reverse lexicographical */ i = ht->evl-1; while (i > 1 && ea[i] == eb[i]) { --i; } return eb[i] - ea[i]; } static int initial_gens_cmp_drl( const void *a, const void *b, void *htp ) { len_t i; ht_t *ht = htp; const hm_t ha = **(hm_t **)a; const hm_t hb = **(hm_t **)b; const exp_t * const ea = ht->ev[ha]; const exp_t * const eb = ht->ev[hb]; /* DRL */ if (ea[DEG] < eb[DEG]) { return 1; } else { if (ea[DEG] != eb[DEG]) { return -1; } } /* note: reverse lexicographical */ i = ht->evl-1; while (i > 1 && ea[i] == eb[i]) { --i; } return ea[i] - eb[i]; } static int monomial_cmp_pivots_drl( const hi_t a, const hi_t b, const ht_t * const ht ) { len_t i; const hd_t ha = ht->hd[a]; const hd_t hb = ht->hd[b]; #if ORDER_COLUMNS /* first known pivots vs. tail terms */ if (ha.idx != hb.idx) { if (ha.idx < hb.idx) { return 1; } else { return -1; } } #endif const exp_t * const ea = ht->ev[a]; const exp_t * const eb = ht->ev[b]; /* then DRL */ if (ea[DEG] > eb[DEG]) { return -1; } else { if (ea[DEG] != eb[DEG]) { return 1; } } /* note: reverse lexicographical */ i = ht->evl-1; while (i > 1 && ea[i] == eb[i]) { --i; } return ea[i] - eb[i]; } static inline int monomial_cmp_drl( const hi_t a, const hi_t b, const ht_t *ht ) { len_t i; if (a == b) { return 0; } const exp_t * const ea = ht->ev[a]; const exp_t * const eb = ht->ev[b]; /* DRL */ if (ea[DEG] > eb[DEG]) { return 1; } else { if (ea[DEG] != eb[DEG]) { return -1; } } i = ht->evl-1; while (i > 1 && ea[i] == eb[i]) { --i; } return eb[i] - ea[i]; } /* comparison for hash-column-maps */ static int hcm_cmp_pivots_drl( const void *a, const void *b, void *htp ) { const ht_t *ht = (ht_t *)htp; const hi_t ma = ((hi_t *)a)[0]; const hi_t mb = ((hi_t *)b)[0]; return monomial_cmp_pivots_drl(ma, mb, ht); } static int spair_cmp_update( const void *a, const void *b, void *htp) { const spair_t *sa = ((spair_t *)a); const spair_t *sb = ((spair_t *)b); const ht_t *ht = (ht_t *)htp; if (sa->lcm != sb->lcm) { return (int)monomial_cmp(sa->lcm, sb->lcm, ht); } else { if (sa->deg != sb->deg) { return (sa->deg < sb->deg) ? -1 : 1; } else { if (sa->gen1 != sb->gen1) { return (sa->gen1 < sb->gen1) ? -1 : 1; } else { return 0; } } } } static int spair_cmp_drl( const void *a, const void *b, void *htp ) { const hi_t la = ((spair_t *)a)->lcm; const hi_t lb = ((spair_t *)b)->lcm; const ht_t *ht = (ht_t *)htp; int mc = (int)monomial_cmp(la, lb, ht); if (mc != 0) { if (mc < 0) return -1; else return 1; /* return mc; */ } /* if (((spair_t *)a)->gen1 < ((spair_t *)b)->gen1) { * return -1; * } * if (((spair_t *)a)->gen1 > ((spair_t *)b)->gen1) { * return 1; * } * if (((spair_t *)a)->gen2 < ((spair_t *)b)->gen2) { * return -1; * } * if (((spair_t *)a)->gen2 > ((spair_t *)b)->gen2) { * return 1; * } */ return 0; } /* * IMPLEMENTATIONS FOR BLOCK ELIMINATION ORDER: * 2 blocks, each block handled by the degree * reverse lexicographical order * */ static int initial_input_cmp_be( const void *a, const void *b, void *htp ) { len_t i; ht_t *ht = htp; const hm_t ha = ((hm_t **)a)[0][OFFSET]; const hm_t hb = ((hm_t **)b)[0][OFFSET]; const exp_t * const ea = ht->ev[ha]; const exp_t * const eb = ht->ev[hb]; /* first block */ if (ea[0] < eb[0]) { return -1; } else { if (ea[DEG] != eb[DEG]) { return 1; } } /* note: reverse lexicographical */ i = ht->ebl-1; while (i > 1 && ea[i] == eb[i]) { --i; } if (eb[i] - ea[i] != 0) { return eb[i] - ea[i]; } else { /* second block */ if (ea[ht->ebl] < eb[ht->ebl]) { return -1; } else { if (ea[ht->ebl] != eb[ht->ebl]) { return 1; } } /* note: reverse lexicographical */ i = ht->evl-1; while (i > ht->ebl && ea[i] == eb[i]) { --i; } return eb[i] - ea[i]; } } static int initial_gens_cmp_be( const void *a, const void *b, void *htp ) { len_t i; ht_t *ht = htp; const hm_t ha = **(hm_t **)a; const hm_t hb = **(hm_t **)b; const exp_t * const ea = ht->ev[ha]; const exp_t * const eb = ht->ev[hb]; /* first block */ if (ea[0] < eb[0]) { return 1; } else { if (ea[0] != eb[0]) { return -1; } } /* note: reverse lexicographical */ i = ht->ebl-1; while (i > 1 && ea[i] == eb[i]) { --i; } if (ea[i] - eb[i] != 0) { return ea[i] - eb[i]; } else { /* second block */ if (ea[ht->ebl] < eb[ht->ebl]) { return 1; } else { if (ea[ht->ebl] != eb[ht->ebl]) { return -1; } } /* note: reverse lexicographical */ i = ht->evl-1; while (i > ht->ebl && ea[i] == eb[i]) { --i; } return ea[i] - eb[i]; } } static int monomial_cmp_pivots_be( const hi_t a, const hi_t b, const ht_t * const ht ) { len_t i; const hd_t ha = ht->hd[a]; const hd_t hb = ht->hd[b]; #if ORDER_COLUMNS /* first known pivots vs. tail terms */ if (ha.idx != hb.idx) { if (ha.idx < hb.idx) { return 1; } else { return -1; } } #endif const exp_t * const ea = ht->ev[a]; const exp_t * const eb = ht->ev[b]; /* first block */ if (ea[0] > eb[0]) { return -1; } else { if (ea[0] != eb[0]) { return 1; } } /* note: reverse lexicographical */ i = ht->ebl-1; while (i > 1 && ea[i] == eb[i]) { --i; } if (ea[i] - eb[i] != 0) { return ea[i] - eb[i]; } else { /* second block */ if (ea[ht->ebl] > eb[ht->ebl]) { return -1; } else { if (ea[ht->ebl] != eb[ht->ebl]) { return 1; } } /* note: reverse lexicographical */ i = ht->evl-1; while (i > ht->ebl && ea[i] == eb[i]) { --i; } return ea[i] - eb[i]; } } static inline int monomial_cmp_be( const hi_t a, const hi_t b, const ht_t *ht ) { len_t i; if (a == b) { return 0; } const exp_t * const ea = ht->ev[a]; const exp_t * const eb = ht->ev[b]; /* first block */ if (ea[0] > eb[0]) { return 1; } else { if (ea[0] != eb[0]) { return -1; } } i = ht->ebl-1; while (i > 1 && ea[i] == eb[i]) { --i; } if (eb[i] - ea[i] != 0) { return eb[i] - ea[i]; } else { /* second block */ if (ea[ht->ebl] > eb[ht->ebl]) { return 1; } else { if (ea[ht->ebl] != eb[ht->ebl]) { return -1; } } i = ht->evl-1; while (i > ht->ebl && ea[i] == eb[i]) { --i; } return eb[i] - ea[i]; } } /* comparison for hash-column-maps */ static int hcm_cmp_pivots_be( const void *a, const void *b, void *htp ) { const ht_t *ht = (ht_t *)htp; const hi_t ma = ((hi_t *)a)[0]; const hi_t mb = ((hi_t *)b)[0]; return monomial_cmp_pivots_be(ma, mb, ht); } static int spair_cmp_be( const void *a, const void *b, void *htp ) { const hi_t da = ((spair_t *)a)->deg; const hi_t db = ((spair_t *)b)->deg; if (da - db != 0) { return da - db; } else { const hi_t la = ((spair_t *)a)->lcm; const hi_t lb = ((spair_t *)b)->lcm; const ht_t *ht = (ht_t *)htp; int mc = (int)monomial_cmp(la, lb, ht); if (mc != 0) { if (mc < 0) { return -1; } else { return 1; } } } return 0; } /* * IMPLEMENTATIONS FOR SIGNATURE BASED ALGORITHMS * */ static int initial_input_cmp_sig( const void *a, const void *b, void *htp ) { len_t i; ht_t *ht = htp; const hm_t ha = ((hm_t **)a)[0][OFFSET]; const hm_t hb = ((hm_t **)b)[0][OFFSET]; const exp_t * const ea = ht->ev[ha]; const exp_t * const eb = ht->ev[hb]; /* DRL */ if (ea[DEG] < eb[DEG]) { return 1; } else { if (ea[DEG] != eb[DEG]) { return -1; } } /* note: reverse lexicographical */ i = ht->evl-1; while (i > 1 && ea[i] == eb[i]) { --i; } return ea[i] - eb[i]; } static int matrix_row_cmp_by_increasing_signature( const void *a, const void *b, void *htp ) { const ht_t *ht = (ht_t *)htp; hm_t sig_a, sig_b; /* compare pivot resp. column index */ sig_a = ((hm_t **)a)[0][SM_SMON]; sig_b = ((hm_t **)b)[0][SM_SMON]; int diff = (int)monomial_cmp(sig_a, sig_b, ht); if (diff != 0) { return diff; } else { int sidx_a, sidx_b; sidx_a = (int)((hm_t **)a)[0][SM_SIDX]; sidx_b = (int)((hm_t **)b)[0][SM_SIDX]; return sidx_b - sidx_a; } } static inline void sort_matrix_rows_by_increasing_signature( smat_t *smat, void *htp ) { hm_t **cr = smat->cr; sort_r(cr, (unsigned long)smat->cld, sizeof(hm_t *), &matrix_row_cmp_by_increasing_signature, htp); } msolve-0.6.5/src/neogb/sba.c000066400000000000000000000543331456710632100156360ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "sba.h" static inline crit_t *initialize_signature_criteria( const md_t * const st ) { crit_t *crit = calloc((unsigned long)st->ngens, sizeof(crit_t)); for (int i = 0; i < st->ngens; ++i) { crit[i].sz = 8; crit[i].sdm = realloc(crit[i].sdm, (unsigned long)crit[i].sz * sizeof(sdm_t)); crit[i].hm = realloc(crit[i].hm, (unsigned long)crit[i].sz * sizeof(hm_t)); } return crit; } static inline void reset_signature_criteria( crit_t *crit, const md_t * const st ) { for (len_t i = 0; i < st->ngens; ++i) { crit[i].ld = 0; } } static inline void free_signature_criteria( crit_t **critp, const md_t * const st ) { crit_t *crit = *critp; for (len_t i = 0; i < st->ngens; ++i) { free(crit[i].sdm); crit[i].sdm = NULL; free(crit[i].hm); crit[i].hm = NULL; crit[i].ld = 0; } free(crit); crit = NULL; *critp = crit; } static len_t sba_add_new_elements_to_basis( const smat_t * const smat, const ht_t * const ht, bs_t *bs, const md_t * const st ) { len_t i, j, k, ne; const len_t nr = smat->cld; const len_t bld = bs->ld; bs->lo = bld; /* row indices of new elements are getting precached */ len_t *rine = calloc((unsigned long)nr, sizeof(len_t)); k = 0; i = 0; next: for (; i < nr; ++i) { /* printf("possible new element[%u] = ", i); * for (int ii = 0; ii < ht->evl; ++ii) { * printf("%u ", ht->ev[smat->cr[i][SM_OFFSET]][ii]); * } * printf("\n"); */ const hm_t lm = smat->cr[i][SM_OFFSET]; for (j = 0; j < bld; ++j) { /* printf("check div with %u | ", j); * for (int ii = 0; ii < ht->evl; ++ii) { * printf("%u ", ht->ev[bs->hm[j][OFFSET]][ii]); * } * printf("\n"); */ if (check_monomial_division(lm, bs->hm[j][OFFSET], ht) == 1) { i++; goto next; } } rine[k++] = i; } check_enlarge_basis(bs, k, st); /* now enter elements to basis */ for (i = 0; i < k; ++i) { /* printf("coming from signature "); * for (int ii = 0; ii < ht->evl; ++ii) { * printf("%u ", ht->ev[smat->cr[rine[i]][SM_SMON]][ii]); * } * printf("| %u\n", smat->cr[rine[i]][SM_SIDX]); */ bs->hm[bs->ld] = (hm_t *)malloc( (unsigned long)(smat->cr[rine[i]][SM_LEN]+OFFSET) * sizeof(hm_t)); memcpy(bs->hm[bs->ld]+PRELOOP, smat->cr[rine[i]]+SM_PRE, (unsigned long)(smat->cr[rine[i]][SM_LEN]+SM_OFFSET-SM_PRE) * sizeof(hm_t)); bs->cf_32[bs->ld] = (cf32_t *)malloc( (unsigned long)(smat->cr[rine[i]][SM_LEN]) * sizeof(cf32_t)); memcpy(bs->cf_32[bs->ld], smat->cc32[smat->cr[rine[i]][SM_CFS]], (unsigned long)(smat->cr[rine[i]][SM_LEN]) * sizeof(cf32_t)); /* We assume that the polynomials are homogeneous */ bs->hm[bs->ld][DEG] = ht->hd[bs->hm[bs->ld][OFFSET]].deg; bs->hm[bs->ld][COEFFS] = bs->ld; /* printf("new bs[%u] = ", bs->ld); * for (int ii = 0; ii < ht->evl; ++ii) { * printf("%u ", ht->ev[bs->hm[bs->ld][OFFSET]][ii]); * } * printf("\n"); */ bs->ld++; } free(rine); rine = NULL; /* check number of new elements here, later on bs->ld might change */ ne = k; /* If the input is NOT homogeneous, check if the new elements in * the basis makes older elements redundant. */ if (st->homogeneous != 1) { /* Note: Now, bs->ld is the new load of the basis after adding * new elements, bld was set before thus it represents the old * load of the basis. */ const len_t bln = bs->ld; k = 0; i = 0; next_element: for (; i < bld; ++i) { const hm_t lm = bs->hm[i][OFFSET]; for (j = bld; j < bln; ++j) { if (check_monomial_division(bs->hm[j][OFFSET], lm, ht) == 1) { free(bs->hm[i]); bs->hm[i] = NULL; free(bs->cf_32[i]); bs->cf_32[i] = NULL; i++; goto next_element; } } bs->hm[k] = bs->hm[i]; bs->cf_32[k] = bs->cf_32[i]; k++; } /* now add new elements correctly in minimized basis */ for (i = bld; i < bln; ++i) { bs->hm[k] = bs->hm[i]; bs->cf_32[k] = bs->cf_32[i]; bs->hm[k][COEFFS] = k; k++; } bs->ld = k; } return ne; } static int is_signature_needed( const smat_t * const smat, const crit_t * const syz, const crit_t * const rew, const len_t idx, const len_t var_idx, ht_t *ht, md_t *st ) { len_t i; /* get exponent vector and increment entry for var_idx */ exp_t *ev = ht->ev[0]; memcpy(ev, ht->ev[smat->pr[idx][SM_SMON]], (unsigned long)ht->evl * sizeof(exp_t));; /* Note: ht->ebl = #elimination variables + 1 */ len_t shift = var_idx < ht->ebl - 1 ? 1: 2; len_t deg_pos = shift == 2 ? ht->ebl : 0; ev[var_idx+shift]++; ev[deg_pos]++; const len_t sig_idx = smat->pr[idx][SM_SIDX]; /* printf("check signature "); * for (int ii = 0; ii < ht->evl; ++ii) { * printf("%u ", ev[ii]); * } * printf("| %u\n", sig_idx); */ const hm_t hm = insert_in_hash_table(ev, ht); const sdm_t nsdm = ~ht->hd[hm].sdm; const len_t evl = ht->evl; /* printf("---syzgyies---\n"); * for (int jj = 0; jj < syz[sig_idx].ld; ++jj) { * for (int kk = 0; kk < ht->evl; ++kk) { * printf("%u ", ht->ev[syz[sig_idx].hm[jj]][kk]); * } * printf("| %u\n", sig_idx); * } * * printf("---rewriters---\n"); * for (int jj = 0; jj < rew[sig_idx].ld; ++jj) { * for (int kk = 0; kk < ht->evl; ++kk) { * printf("%u ", ht->ev[rew[sig_idx].hm[jj]][kk]); * } * printf("| %u\n", sig_idx); * } */ #if 1 /* syzygy criterion */ i = 0; syz: ; const crit_t syz_idx = syz[sig_idx]; for (; i < syz_idx.ld; ++i) { if (nsdm & syz_idx.sdm[i]) { continue; } const exp_t *sev = ht->ev[syz_idx.hm[i]]; for (len_t j = 0; j < evl; ++j) { if (sev[j] > ev[j]) { i++; goto syz; } } st->num_syz_crit++; /* printf("syz crit applies\n"); */ return 0; } /* rewrite criterion */ i = 0; rew: ; const crit_t rew_idx = rew[sig_idx]; for (; i < rew_idx.ld; ++i) { if (nsdm & rew_idx.sdm[i]) { continue; } const exp_t *rev = ht->ev[rew_idx.hm[i]]; for (len_t j = 0; j < evl; ++j) { if (rev[j] > ev[j]) { i++; goto rew; } } st->num_rew_crit++; /* printf("rew crit applies\n"); */ return 0; } #endif return 1; } static inline void enlarge_sba_matrix( smat_t *smat ) { smat->csz *= 2; smat->cr = realloc( smat->cr, (unsigned long)smat->csz * sizeof(hm_t *)); smat->cc32 = realloc( smat->cc32, (unsigned long)smat->csz * sizeof(cf32_t *)); smat->pc32 = realloc( smat->pc32, (unsigned long)smat->csz * sizeof(cf32_t *)); } static inline void check_enlarge_signature_rule_array( crit_t *rew, const len_t sidx ) { if (rew[sidx].ld >= rew[sidx].sz) { rew[sidx].sz *= 2; rew[sidx].sdm = realloc(rew[sidx].sdm, (unsigned long)rew[sidx].sz * sizeof(sdm_t)); rew[sidx].hm = realloc(rew[sidx].hm, (unsigned long)rew[sidx].sz * sizeof(hm_t)); } } static inline void add_rewrite_rule( crit_t *rew, const smat_t * const smat, const len_t idx, const ht_t * const ht ) { const len_t sidx = smat->pr[idx][SM_SIDX]; check_enlarge_signature_rule_array(rew, sidx); rew[sidx].hm[rew[sidx].ld] = smat->pr[idx][SM_SMON]; rew[sidx].sdm[rew[sidx].ld] = ht->hd[smat->pr[idx][SM_SMON]].sdm; rew[sidx].ld++; } static void add_row_to_sba_matrix( smat_t *smat, const len_t idx, const len_t var_idx, ht_t *ht ) { if (smat->cld >= smat->csz) { enlarge_sba_matrix(smat); } while (ht->esz - ht->eld < smat->pr[idx][SM_LEN]+SM_OFFSET + 1) { enlarge_hash_table(ht); } const len_t cld = smat->cld; /* Note: ht->ebl = #elimination variables + 1 */ len_t shift = var_idx < ht->ebl - 1 ? 1: 2; len_t deg_pos = shift == 2 ? ht->ebl : 0; /* copy monomial entries in row */ smat->cr[cld] = malloc( ((unsigned long)smat->pr[idx][SM_LEN]+SM_OFFSET) * sizeof(hm_t)); memcpy(smat->cr[cld], smat->pr[idx], ((unsigned long)smat->pr[idx][SM_LEN]+SM_OFFSET) * sizeof(hm_t)); /* now multiply each column entry with the corresponding variable */ hm_t *cr = smat->cr[cld]; /* Note that ht->ev[0] is already the multiplied signature, we have already * checked if we need this signature in is_signature_needed(), thus we can * just use it without further updating it. */ exp_t *ev = ht->ev[0]; /* multiply signature */ cr[SM_SMON] = insert_in_hash_table(ev, ht); /* multiply monomials in corresp. polnoymial */ const len_t len = cr[SM_LEN] + SM_OFFSET; for (len_t i = SM_OFFSET; i < len; ++i) { memcpy(ev, ht->ev[cr[i]], (unsigned long)ht->evl * sizeof(exp_t)); ev[var_idx+shift]++; ev[deg_pos]++; cr[i] = insert_in_hash_table(ev, ht); } smat->cld++; } static void add_multiples_of_previous_degree_row( smat_t *smat, const len_t idx, const crit_t * const syz, crit_t *rew, ht_t *ht, md_t *st) { const len_t nv = ht->nv; len_t ctr = 0; while (ht->esz - ht->eld < nv) { enlarge_hash_table(ht); } for (len_t i = 0; i < nv; ++i) { /* check syzygy and rewrite criterion */ if (is_signature_needed(smat, syz, rew, idx, i, ht, st) == 1) { add_row_to_sba_matrix(smat, idx, i, ht); ctr++; } } /* if we have added at least one multiple of the previous degree * row we can add its signature to the rewrite rule array */ if (ctr > 0) { /* add rewrite rule */ add_rewrite_rule(rew, smat, idx, ht); } } static inline void add_row_with_signature( smat_t *smat, const bs_t * const bs, const len_t pos ) { /* here we introduce initial generators to the matrix, note * that memory was already allocated correspondingly when * we prepared the next degree step */ const len_t cld = smat->cld; const len_t pld = smat->pld; const len_t len = bs->hm[pos][LENGTH]; smat->cr[cld] = (hm_t *)malloc( (len + SM_OFFSET) * sizeof(hm_t)); /* copy polynomial data, take a look at the difference between * the meta data stored in hm arrays from bs and the * meta data stored in signature-based smat rows. */ memcpy(smat->cr[cld]+SM_PRE,bs->hm[pos]+PRELOOP, (len + OFFSET - PRELOOP) * sizeof(hm_t)); smat->pc32[pld] = bs->cf_32[bs->hm[pos][COEFFS]]; smat->cr[cld][SM_CFS] = pld; /* store also signature data */ smat->cr[cld][SM_SMON] = bs->sm[pos]; smat->cr[cld][SM_SIDX] = bs->si[pos]; smat->cld++; smat->pld++; } inline void add_syzygy_schreyer( crit_t *syz, const hm_t sm, const len_t si, const ht_t * const ht ) { check_enlarge_signature_rule_array(syz, si); syz[si].hm[syz[si].ld] = sm; syz[si].sdm[syz[si].ld] = ht->hd[sm].sdm; syz[si].ld++; } static inline crit_t *initialize_syzygies_schreyer( const bs_t * const bs, ht_t *ht ) { const len_t bld = bs->ld; /* when initializing syzygies we assume that bs->ld == st->ngens */ crit_t *syz = calloc((unsigned long)bs->ld, sizeof(crit_t)); syz[0].ld = 0; syz[0].sz = 0; /* We allocate one more slot of memory than needed, thus also * for signature index bs->ld-1 we have at least one open * slot for fewer size checks if enlargement of the syzygy * rule arrays are needed later on. */ for (len_t i = 0; i < bld; ++i) { syz[i].hm = calloc((unsigned long)bld-i, sizeof(hm_t)); syz[i].sdm = calloc((unsigned long)bld-i, sizeof(sdm_t)); syz[i].ld = 0; syz[i].sz = bld-i; for (len_t j = i+1; j < bld; ++j) { syz[i].hm[j] = insert_multiplied_signature_in_hash_table( bs->hm[j][OFFSET], bs->sm[i], ht); syz[i].sdm[j] = ht->hd[syz[i].hm[j]].sdm; /* printf("init syz[%u] -> ", i); * for (int ii = 0; iievl; ++ii) { * printf("%u ", ht->ev[syz[i].hm[j]][ii]); * } * printf("\n"); */ } syz[i].ld = bld-1-i; /* printf("\n"); */ } return syz; } static inline void initialize_signatures_schreyer( bs_t *bs ) { for (len_t i = 0; i < bs->ld; ++i) { bs->si[i] = i; bs->sm[i] = bs->hm[i][OFFSET]; } } static inline void initialize_signatures_not_schreyer( bs_t *bs ) { for (len_t i = 0; i < bs->ld; ++i) { bs->si[i] = i; bs->sm[i] = 0; } } static void sba_prepare_next_degree( smat_t *smat, const bs_t * const in, const len_t ni, /* number of input generators added */ const md_t * const st ) { smat->pr = smat->cr; smat->pc32 = smat->cc32; smat->pld = smat->cld; /* reset smat data */ smat->cc32 = NULL; smat->cld = smat->csz = smat->nz = smat->nc = 0; smat->csz = (smat->pld * st->nvars) + ni; smat->cr = (hm_t **)calloc( (unsigned long)smat->csz,sizeof(hm_t *)); /* allocate memory to store initial generators in pr and pc32 */ smat->pc32 = realloc(smat->pc32, (unsigned long)(smat->pld + ni) * sizeof(cf32_t *)); } static len_t get_number_of_initial_generators_in_next_degree( const bs_t * const in, const deg_t nd /* next degree */ ) { len_t ctr = 0; int32_t i = in->ld-1; while (i >= 0 && in->hm[i][DEG] == nd) { ctr++; i--; } return ctr; } static void add_initial_generators( smat_t *smat, bs_t *in, const len_t ne ) { len_t j = 0; len_t i = in->ld-1; while (j < ne) { add_row_with_signature(smat, in, i); /* memory for coeffs vector is freed in sba * linear algebra later on */ in->cf_32[in->hm[i][COEFFS]] = NULL; free(in->hm[i]); in->hm[i] = NULL; in->ld--; i--; j++; } } static void generate_next_degree_matrix_from_previous( smat_t *smat, const crit_t * const syz, crit_t *rew, ht_t *ht, md_t *st ) { const len_t pld = smat->pld; for (len_t i = pld; i > 0 ; --i) { add_multiples_of_previous_degree_row(smat, i-1, syz, rew, ht, st); free(smat->pr[i-1]); smat->pr[i-1] = NULL; } } static void sba_final_reduction_step( bs_t *bs, ht_t **htp, hi_t **hcmp, md_t *st ) { ht_t *ht = *htp; hi_t *hcm = *hcmp; /* prepare basis data to apply final reduction process */ for (len_t i = 0; i < bs->ld; ++i) { bs->lm[i] = ht->hd[bs->hm[i][SM_OFFSET]].sdm; bs->lmps[i] = i; } bs->lml = bs->ld; ht_t *sht = initialize_secondary_hash_table(ht, st); mat_t *mat = (mat_t *)calloc(1, sizeof(mat_t)); /* note: bht will become sht, and sht will become NULL, * thus we need pointers */ reduce_basis(bs, mat, st); if (sht != NULL) { free_hash_table(&sht); } free(mat); mat = NULL; *htp = ht; *hcmp = hcm; } static void free_sba_matrix( smat_t **smatp ) { smat_t *smat = *smatp; for (len_t i = 0; i < smat->cld; ++i) { free(smat->cr[i]); free(smat->cc32[i]); } for (len_t i = 0; i < smat->pld; ++i) { free(smat->pc32[i]); } free(smat); smat = NULL; *smatp = smat; } static void generate_next_degree_sba_matrix( smat_t *smat, bs_t *in, crit_t *syz, crit_t *rew, ht_t *ht, md_t *st ) { /* check if we have initial generators not handled in lower degree * until now */ const len_t ni = get_number_of_initial_generators_in_next_degree( in, smat->cd); /* prepare signature matrix for next degree */ sba_prepare_next_degree(smat, in, ni, st); reset_signature_criteria(rew, st); /* generate rows from previous degree matrix, start with the highest * signatures in order to get an efficient rewrite criterion test */ generate_next_degree_matrix_from_previous( smat, syz, rew, ht, st); add_initial_generators(smat, in, ni); } int core_sba_schreyer( bs_t **bsp, ht_t **htp, md_t **stp ) { bs_t *in = *bsp; ht_t *ht = *htp; md_t *st = *stp; /* timings for one round */ double rrt0, rrt1; int try_termination = 0; /* hashes-to-columns map, initialized with length 1, is reallocated * in each call when generating matrices for linear algebra */ hi_t *hcm = (hi_t *)malloc(sizeof(hi_t)); /* signature matrix and previous degree signature matrix */ smat_t *smat = calloc(1, sizeof(smat_t)); /* initial degree is the lowest degree of the input generators */ smat->cd = in->hm[in->ld-1][DEG]; /* initialize signature related information */ initialize_signatures_schreyer(in); /* printf("initial signatures\n"); * for (int j = 0; j < in->ld; ++j) { * for (int i = 0; i < ht->evl; ++i) { * printf("%u ", ht->ev[in->sm[j]][i]); * } * printf(" | %u --> %u\n", in->si[j], in->sm[j]); * } */ /* crit_t *syz = initialize_syzygies_schreyer(in, ht); */ crit_t *syz = initialize_signature_criteria(st); crit_t *rew = initialize_signature_criteria(st); /* initialize an empty basis for keeping the real basis elements */ bs_t *bs = initialize_basis(st); /* sort initial elements, highest lead term first */ sort_r(in->hm, (unsigned long)in->ld, sizeof(hm_t *), initial_input_cmp_sig, ht); if (st->info_level > 1) { printf("\n deg mat density \ new data time(rd)\n"); printf("-------------------------------------------------\ ----------------------------\n"); } st->current_rd = 0; while (!try_termination) { rrt0 = realtime(); st->max_bht_size = st->max_bht_size > ht->esz ? st->max_bht_size : ht->esz; st->current_rd++; /* generate matrix for next degree step */ generate_next_degree_sba_matrix(smat, in, syz, rew, ht, st); /* sort matrix rows by increasing signature */ sort_matrix_rows_by_increasing_signature(smat, ht); /* for (int ii = 0; ii < smat->cld; ++ii) { * printf("%u | %u \n", smat->cr[ii][SM_SMON], smat->cr[ii][SM_SIDX]); * } */ /* map hashes to columns */ sba_convert_hashes_to_columns(&hcm, smat, st, ht); /* s-reduce matrix and add syzygies when rows s-reduce to zero */ sba_linear_algebra(smat, syz, st, ht); /* maps columns to hashes */ sba_convert_columns_to_hashes(smat, hcm); /* reset indices in hash table*/ reset_hash_table_indices(ht, hcm, smat->nc); /* add new elements to basis */ smat->nlm = sba_add_new_elements_to_basis(smat, ht, bs, st); /* increase degree for next round */ smat->cd++; if (st->info_level > 1) { printf("%7d new %7d zero", smat->nlm, smat->nz); fflush(stdout); } /* if we found a constant we are done, if we have added no new elements * we assume we are done*/ if (bs->constant == 1 || smat->nlm == 0) { try_termination = 1; } rrt1 = realtime(); if (st->info_level > 1) { printf("%13.2f sec\n", rrt1-rrt0); } } /* Note: We cannot free all signature related data at this point, maybe * we terminated too early and need to further compute in higher degrees. */ if (st->info_level > 1) { printf("-------------------------------------------------\ ----------------------------\n"); } /* fully reduce elements in basis. */ if (st->reduce_gb == 1) { sba_final_reduction_step(bs, &ht, &hcm, st); } *bsp = bs; *htp = ht; *stp = st; /* free and clean up */ free_sba_matrix(&smat); free_signature_criteria(&syz, st); free_signature_criteria(&rew, st); free(hcm); printf("size of basis %7u\n", bs->ld); printf("#syzygy criteria %7ld\n", (long)st->num_syz_crit); printf("#rewrite criteria %7ld\n", (long)st->num_rew_crit); return 1; } msolve-0.6.5/src/neogb/sba.h000066400000000000000000000020151456710632100156310ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef GB_SBA_H #define GB_SBA_H #include "data.h" void add_syzygy_schreyer( crit_t *syz, const hm_t sm, const len_t si, const ht_t * const ht ); int core_sba_schreyer( bs_t **bsp, ht_t **bhtp, md_t **stp ); #endif msolve-0.6.5/src/neogb/sort_r.h000066400000000000000000000241541456710632100164040ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ /* Initial version by Isaac Turner 29 April 2014 Public Domain */ #ifndef SORT_R_H_ #define SORT_R_H_ #include #include /* sort_r function to be exported. Parameters: base is the array to be sorted nel is the number of elements in the array width is the size in bytes of each element of the array compar is the comparison function arg is a pointer to be passed to the comparison function void sort_r(void *base, size_t nel, size_t width, int (*compar)(const void *_a, const void *_b, void *_arg), void *arg); */ #define _SORT_R_INLINE inline #if (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || \ defined __FreeBSD__ || defined __DragonFly__) # define _SORT_R_BSD #elif (defined __MINGW32__ || defined __GLIBC__) # define _SORT_R_LINUX #elif (defined _WIN32 || defined _WIN64 || defined __WINDOWS__) # define _SORT_R_WINDOWS # undef _SORT_R_INLINE # define _SORT_R_INLINE __inline #else /* Using our own recursive quicksort sort_r_simple() */ #endif #if (defined NESTED_QSORT && NESTED_QSORT == 0) # undef NESTED_QSORT #endif #define SORT_R_SWAP(a,b,tmp) ((tmp) = (a), (a) = (b), (b) = (tmp)) /* swap a and b */ /* a and b must not be equal! */ static _SORT_R_INLINE void sort_r_swap(char *__restrict a, char *__restrict b, size_t w) { char tmp, *end = a+w; for(; a < end; a++, b++) { SORT_R_SWAP(*a, *b, tmp); } } /* swap a, b iff a>b */ /* a and b must not be equal! */ /* __restrict is same as restrict but better support on old machines */ static _SORT_R_INLINE int sort_r_cmpswap(char *__restrict a, char *__restrict b, size_t w, int (*compar)(const void *_a, const void *_b, void *_arg), void *arg) { if(compar(a, b, arg) > 0) { sort_r_swap(a, b, w); return 1; } return 0; } /* Swap consecutive blocks of bytes of size na and nb starting at memory addr ptr, with the smallest swap so that the blocks are in the opposite order. Blocks may be internally re-ordered e.g. 12345ab -> ab34512 123abc -> abc123 12abcde -> deabc12 */ static _SORT_R_INLINE void sort_r_swap_blocks(char *ptr, size_t na, size_t nb) { if(na > 0 && nb > 0) { if(na > nb) { sort_r_swap(ptr, ptr+na, nb); } else { sort_r_swap(ptr, ptr+nb, na); } } } /* Implement recursive quicksort ourselves */ /* Note: quicksort is not stable, equivalent values may be swapped */ static _SORT_R_INLINE void sort_r_simple(void *base, size_t nel, size_t w, int (*compar)(const void *_a, const void *_b, void *_arg), void *arg) { char *b = (char *)base, *end = b + nel*w; /* for(size_t i=0; i b && sort_r_cmpswap(pj-w,pj,w,compar,arg); pj -= w) {} } } else { /* nel > 6; Quicksort */ int cmp; char *pl, *ple, *pr, *pre, *pivot; char *last = b+w*(nel-1), *tmp; /* Use median of second, middle and second-last items as pivot. First and last may have been swapped with pivot and therefore be extreme */ char *l[3]; l[0] = b + w; l[1] = b+w*(nel/2); l[2] = last - w; /* printf("pivots: %i, %i, %i\n", *(int*)l[0], *(int*)l[1], *(int*)l[2]); */ if(compar(l[0],l[1],arg) > 0) { SORT_R_SWAP(l[0], l[1], tmp); } if(compar(l[1],l[2],arg) > 0) { SORT_R_SWAP(l[1], l[2], tmp); if(compar(l[0],l[1],arg) > 0) { SORT_R_SWAP(l[0], l[1], tmp); } } /* swap mid value (l[1]), and last element to put pivot as last element */ if(l[1] != last) { sort_r_swap(l[1], last, w); } /* pl is the next item on the left to be compared to the pivot pr is the last item on the right that was compared to the pivot ple is the left position to put the next item that equals the pivot ple is the last right position where we put an item that equals the pivot v- end (beyond the array) EEEEEELLLLLLLLuuuuuuuuGGGGGGGEEEEEEEE. ^- b ^- ple ^- pl ^- pr ^- pre ^- last (where the pivot is) Pivot comparison key: E = equal, L = less than, u = unknown, G = greater than, E = equal */ pivot = last; ple = pl = b; pre = pr = last; /* Strategy: Loop into the list from the left and right at the same time to find: - an item on the left that is greater than the pivot - an item on the right that is less than the pivot Once found, they are swapped and the loop continues. Meanwhile items that are equal to the pivot are moved to the edges of the array. */ while(pl < pr) { /* Move left hand items which are equal to the pivot to the far left. break when we find an item that is greater than the pivot */ for(; pl < pr; pl += w) { cmp = compar(pl, pivot, arg); if(cmp > 0) { break; } else if(cmp == 0) { if(ple < pl) { sort_r_swap(ple, pl, w); } ple += w; } } /* break if last batch of left hand items were equal to pivot */ if(pl >= pr) { break; } /* Move right hand items which are equal to the pivot to the far right. break when we find an item that is less than the pivot */ for(; pl < pr; ) { pr -= w; /* Move right pointer onto an unprocessed item */ cmp = compar(pr, pivot, arg); if(cmp == 0) { pre -= w; if(pr < pre) { sort_r_swap(pr, pre, w); } } else if(cmp < 0) { if(pl < pr) { sort_r_swap(pl, pr, w); } pl += w; break; } } } pl = pr; /* pr may have gone below pl */ /* Now we need to go from: EEELLLGGGGEEEE to: LLLEEEEEEEGGGG Pivot comparison key: E = equal, L = less than, u = unknown, G = greater than, E = equal */ sort_r_swap_blocks(b, (size_t)(ple-b), (size_t)(pl-ple)); sort_r_swap_blocks(pr, (size_t)(pre-pr), (size_t)(end-pre)); /*for(size_t i=0; icompar)(a, b, ss->arg); } #endif #if defined _SORT_R_LINUX typedef int(* __compar_d_fn_t)(const void *, const void *, void *); extern void qsort_r(void *base, size_t nel, size_t width, __compar_d_fn_t __compar, void *arg) __attribute__((nonnull (1, 4))); #endif /* implementation */ static _SORT_R_INLINE void sort_r(void *base, size_t nel, size_t width, int (*compar)(const void *_a, const void *_b, void *_arg), void *arg) { #if defined _SORT_R_LINUX #if defined __GLIBC__ && ((__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 8)) /* no qsort_r in glibc before 2.8, need to use nested qsort */ sort_r_simple(base, nel, width, compar, arg); #else qsort_r(base, nel, width, compar, arg); #endif #elif defined _SORT_R_BSD struct sort_r_data tmp; tmp.arg = arg; tmp.compar = compar; qsort_r(base, nel, width, &tmp, sort_r_arg_swap); #elif defined _SORT_R_WINDOWS struct sort_r_data tmp; tmp.arg = arg; tmp.compar = compar; qsort_s(base, nel, width, sort_r_arg_swap, &tmp); #else /* Fall back to our own quicksort implementation */ sort_r_simple(base, nel, width, compar, arg); #endif } #endif /* !NESTED_QSORT */ #undef _SORT_R_INLINE #undef _SORT_R_WINDOWS #undef _SORT_R_LINUX #undef _SORT_R_BSD #endif /* SORT_R_H_ */ msolve-0.6.5/src/neogb/symbol.c000066400000000000000000000540611456710632100163740ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "data.h" #ifdef HAVE_AVX2 #include #endif /* select_all_pairs() is unused at the moment */ #if 0 static void select_all_spairs( mat_t *mat, const bs_t * const bs, ps_t *psl, md_t *st, ht_t *sht, ht_t *bht, ht_t *tht ) { len_t i, j, k, l, nps, npd, nrr = 0, ntr = 0; hm_t *b; len_t load = 0; hi_t lcm; len_t *gens; exp_t *elcm, *eb; exp_t etmp[bht->evl]; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); spair_t *ps = psl->p; const len_t nv = bht->nv; /* sort pair set */ sort_r(ps, (unsigned long)psl->ld, sizeof(spair_t), spair_degree_cmp, bht); /* select pairs of this degree respecting maximal selection size mnsel */ npd = psl->ld; sort_r(ps, (unsigned long)npd, sizeof(spair_t), spair_cmp, bht); /* now do maximal selection if it applies */ nps = psl->ld; if (st->info_level > 1) { printf("%3d %6d %7d", 0, nps, psl->ld); fflush(stdout); } /* statistics */ st->num_pairsred += nps; /* list for generators */ gens = (len_t *)malloc(2 * (unsigned long)nps * sizeof(len_t)); /* preset matrix meta data */ mat->rr = (hm_t **)malloc(2 * (unsigned long)nps * sizeof(hm_t *)); hm_t **rrows = mat->rr; mat->tr = (hm_t **)malloc(2 * (unsigned long)nps * sizeof(hm_t *)); hm_t **trows = mat->tr; mat->sz = 2 * nps; mat->nc = mat->ncl = mat->ncr = 0; mat->nr = 0; int ctr = 0; i = 0; while (i < nps) { /* ncols initially counts number of different lcms */ mat->nc++; load = 0; lcm = ps[i].lcm; j = i; while (j < nps && ps[j].lcm == lcm) { gens[load++] = ps[j].gen1; gens[load++] = ps[j].gen2; ++j; } /* sort gens set */ qsort(gens, (unsigned long)load, sizeof(len_t), gens_cmp); len_t prev = -1; /* first element with given lcm goes into reducer part of matrix, * all remaining ones go to to be reduced part */ prev = gens[0]; /* printf("prev %u / %u\n", prev, bs->ld); */ /* ev might change when enlarging the hash table during insertion of a new * row in the matrix, thus we have to reset elcm inside the for loop */ elcm = bht->ev[lcm]; b = bs->hm[prev]; eb = bht->ev[b[OFFSET]]; for (l = 0; l <= nv; ++l) { etmp[l] = (exp_t)(elcm[l] - eb[l]); } const hi_t h = bht->hd[lcm].val - bht->hd[b[OFFSET]].val; /* note that we use index mat->nc and not mat->nr since for each new * lcm we add exactly one row to mat->rr */ rrows[nrr] = multiplied_poly_to_matrix_row(sht, bht, h, etmp, b); /* track trace information ? */ if (tht != NULL) { rrows[nrr][BINDEX] = prev; if (tht->eld == tht->esz-1) { enlarge_hash_table(tht); } rrows[nrr][MULT] = insert_in_hash_table(etmp, tht); } /* mark lcm column as lead term column */ sht->hd[rrows[nrr++][OFFSET]].idx = 2; /* still we have to increase the number of rows */ mat->nr++; for (k = 1; k < load; ++k) { /* check sorted list for doubles */ if (gens[k] == prev) { continue; } prev = gens[k]; /* ev might change when enlarging the hash table during insertion of a new * row in the matrix, thus we have to reset elcm inside the for loop */ elcm = bht->ev[lcm]; if (elcm[0] > 0) { /* printf("pair with lcm "); * for (int ii = 0; ii < nv; ++ii) { * printf("%u ", elcm[ii]); * } * printf("\n"); */ } b = bs->hm[prev]; eb = bht->ev[b[OFFSET]]; for (l = 0; l <= nv; ++l) { etmp[l] = (exp_t)(elcm[l] - eb[l]); } const hi_t h = bht->hd[lcm].val - bht->hd[b[OFFSET]].val; trows[ntr] = multiplied_poly_to_matrix_row(sht, bht, h, etmp, b); /* track trace information ? */ if (tht != NULL) { trows[ntr][BINDEX] = prev; if (tht->eld == tht->esz-1) { enlarge_hash_table(tht); } trows[ntr][MULT] = insert_in_hash_table(etmp, tht); } /* mark lcm column as lead term column */ sht->hd[trows[ntr++][OFFSET]].idx = 2; mat->nr++; } ctr++; i = j; } /* printf("nc %u | nr %u || %u\n", mat->nc, mat->nr, sht->eld); */ /* printf("%u pairs in degree %u\n", ctr, md); */ /* fix rows to be reduced */ mat->tr = realloc(mat->tr, (unsigned long)(mat->nr - mat->nc) * sizeof(hm_t *)); st->num_rowsred += mat->nr - mat->nc; st->current_deg = etmp[DEG]; free(gens); /* remove selected spairs from pairset */ memmove(ps, ps+nps, (unsigned long)(psl->ld-nps) * sizeof(spair_t)); psl->ld -= nps; /* timings */ ct1 = cputime(); rt1 = realtime(); st->select_ctime += ct1 - ct0; st->select_rtime += rt1 - rt0; } #endif /* selection of spairs, at the moment only selection by minial degree of the spairs is supported NOTE: The pair list is already sorted! */ static int32_t select_spairs_by_minimal_degree( mat_t *mat, bs_t *bs, md_t *md ) { len_t i, j, k, l, mdeg, nps, npd, nrr = 0, ntr = 0; hm_t *b; len_t load = 0; hi_t lcm; len_t *gens; exp_t *elcm, *eb; ht_t *bht = bs->ht; exp_t etmp[bht->evl]; ps_t *psl = md->ps; ht_t *sht = md->ht; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); spair_t *ps = psl->p; const len_t evl = bht->evl; /* sort pair set */ sort_r(ps, (unsigned long)psl->ld, sizeof(spair_t), spair_cmp, bht); /* get minimal degree */ mdeg = ps[0].deg; /* compute a truncated GB? Check maximal degree. */ if (md->max_gb_degree < mdeg) { return 1; } /* select pairs of this degree respecting maximal selection size mnsel */ #if 0 printf("pair set sorted for symbolic preprocessing\n"); int pctr = 0; deg_t degtest = 0; for (i = 0; i < psl->ld; ++i) { if (degtest != ps[i].deg) { printf("%d elements\n", pctr); printf("-- degree %d --\n", ps[i].deg); degtest = ps[i].deg; pctr = 0; } printf("%d --> deg %d --> [%u,%u]", i, ps[i].deg, ps[i].gen1, ps[i].gen2); for (int jj = 0; jj < evl; ++jj) { printf("%d ", bht->ev[ps[i].lcm][jj]); } pctr++; printf("\n"); } printf("\n"); #endif for (i = 0; i < psl->ld; ++i) { if (ps[i].deg > mdeg) { break; } } npd = i; /* printf("npd %d\n", npd); */ /* sort_r(ps, (unsigned long)npd, sizeof(spair_t), spair_cmp, bht); */ /* now do maximal selection if it applies */ /* if we stopped due to maximal selection size we still get the following * pairs of the same lcm in this matrix */ if (npd > md->mnsel) { nps = md->mnsel; lcm = ps[nps].lcm; while (nps < npd && ps[nps+1].lcm == lcm) { nps++; } } else { nps = npd; } if (md->info_level > 1) { printf("%3d %6d %7d", mdeg, nps, psl->ld); fflush(stdout); } /* statistics */ md->num_pairsred += nps; /* list for generators */ gens = (len_t *)malloc(2 * (unsigned long)nps * sizeof(len_t)); /* preset matrix meta data */ mat->rr = (hm_t **)malloc(2 * (unsigned long)nps * sizeof(hm_t *)); hm_t **rrows = mat->rr; mat->tr = (hm_t **)malloc(2 * (unsigned long)nps * sizeof(hm_t *)); hm_t **trows = mat->tr; mat->sz = 2 * nps; mat->nc = mat->ncl = mat->ncr = 0; mat->nr = 0; i = 0; while (i < nps) { /* ncols initially counts number of different lcms */ mat->nc++; load = 0; lcm = ps[i].lcm; j = i; while (j < nps && ps[j].lcm == lcm) { gens[load++] = ps[j].gen1; gens[load++] = ps[j].gen2; ++j; } /* sort gens set */ qsort(gens, (unsigned long)load, sizeof(len_t), gens_cmp); len_t prev = -1; /* first element with given lcm goes into reducer part of matrix, * all remaining ones go to to be reduced part */ prev = gens[0]; /* ev might change when enlarging the hash table during insertion of a new * row in the matrix, thus we have to reset elcm inside the for loop */ elcm = bht->ev[lcm]; b = bs->hm[prev]; eb = bht->ev[b[OFFSET]]; for (l = 0; l < evl; ++l) { etmp[l] = (exp_t)(elcm[l] - eb[l]); } const hi_t h = bht->hd[lcm].val - bht->hd[b[OFFSET]].val; /* note that we use index mat->nc and not mat->nr since for each new * lcm we add exactly one row to mat->rr */ rrows[nrr] = multiplied_poly_to_matrix_row(sht, bht, h, etmp, b); /* track trace information ? */ if (md->trace_level == LEARN_TRACER) { rrows[nrr][BINDEX] = prev; if (bs->ht->eld == bs->ht->esz-1) { enlarge_hash_table(bs->ht); } #if PARALLEL_HASHING rrows[nrr][MULT] = check_insert_in_hash_table(etmp, h, bs->ht); #else rrows[nrr][MULT] = insert_in_hash_table(etmp, bs->ht); #endif } /* mark lcm column as lead term column */ sht->hd[rrows[nrr++][OFFSET]].idx = 2; /* still we have to increase the number of rows */ mat->nr++; for (k = 1; k < load; ++k) { /* check sorted list for doubles */ if (gens[k] == prev) { continue; } prev = gens[k]; /* ev might change when enlarging the hash table during insertion of a new * row in the matrix, thus we have to reset elcm inside the for loop */ elcm = bht->ev[lcm]; if (elcm[0] > 0) { } b = bs->hm[prev]; eb = bht->ev[b[OFFSET]]; for (l = 0; l < evl; ++l) { etmp[l] = (exp_t)(elcm[l] - eb[l]); } const hi_t h = bht->hd[lcm].val - bht->hd[b[OFFSET]].val; trows[ntr] = multiplied_poly_to_matrix_row(sht, bht, h, etmp, b); /* track trace information ? */ if (md->trace_level == LEARN_TRACER) { trows[ntr][BINDEX] = prev; if (bs->ht->eld == bs->ht->esz-1) { enlarge_hash_table(bs->ht); } #if PARALLEL_HASHING trows[ntr][MULT] = check_insert_in_hash_table(etmp, h, bs->ht); #else trows[ntr][MULT] = insert_in_hash_table(etmp, bs->ht); #endif } /* mark lcm column as lead term column */ sht->hd[trows[ntr++][OFFSET]].idx = 2; mat->nr++; } i = j; } /* printf("%u pairs in degree %u\n", ctr, mdeg); */ /* fix rows to be reduced */ mat->tr = realloc(mat->tr, (unsigned long)(mat->nr - mat->nc) * sizeof(hm_t *)); md->num_rowsred += mat->nr - mat->nc; md->current_deg = mdeg; mat->cd = mdeg; free(gens); /* remove selected spairs from pairset */ memmove(ps, ps+nps, (unsigned long)(psl->ld-nps) * sizeof(spair_t)); psl->ld -= nps; /* timings */ ct1 = cputime(); rt1 = realtime(); md->select_ctime += ct1 - ct0; md->select_rtime += rt1 - rt0; return 0; } /* write elements straight to sat, not to a matrix */ static void select_saturation( bs_t *sat, mat_t *mat, md_t *st, ht_t *sht, ht_t *bht ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* preset matrix meta data */ mat->rr = (hm_t **)malloc(100 * sizeof(hm_t *)); mat->tr = NULL; mat->sz = 100; mat->nc = mat->ncl = mat->ncr = 0; mat->nr = 0; /* for (i=0; i < sat->hm[0][LENGTH]; ++i) { * printf("%u | ", sat->cf_32[sat->hm[0][COEFFS]][i]); * for (len_t j = 0; j < bht->nv; ++j) { * printf("%u ", bht->ev[sat->hm[0][OFFSET+i]][j]); * } * printf(" ||| "); * } * printf("\n"); */ /* move hashes of sat data from bht to sht for linear algebra */ /* for (i = 0; i < sat->ld; ++i) { * for (j = OFFSET; j < sat->hm[i][LENGTH]+OFFSET; ++j) { * sat->hm[i][j] = insert_in_hash_table( * bht->ev[sat->hm[i][j]], sht); * } * } */ /* timings */ ct1 = cputime(); rt1 = realtime(); st->select_ctime += ct1 - ct0; st->select_rtime += rt1 - rt0; } static void select_tbr( const bs_t * const tbr, const exp_t * const mul, const len_t start, mat_t *mat, md_t *st, ht_t *sht, ht_t *bht, ht_t *tht ) { len_t i; len_t ntr = 0; /* preset matrix meta data */ mat->rr = (hm_t **)malloc(100 * sizeof(hm_t *)); mat->tr = (hm_t **)malloc((unsigned long)tbr->ld * sizeof(hm_t *)); hm_t **trows = mat->tr; mat->sz = 100; mat->nc = mat->ncl = mat->ncr = 0; mat->nr = 0; /* always take all elements in tbr and * multiply them by the given multiple */ for (i = start; i < tbr->ld; ++i) { const hm_t *b = tbr->hm[i]; /* remove the multiplier business for the moment, no need * and it corrupts a bit the sht size for efficient matrix * generation */ /* const hi_t mulh = insert_in_hash_table(mul, sht); * const hi_t h = sht->hd[mulh].val; * const deg_t d = sht->hd[mulh].deg; */ const hi_t h = 0; trows[ntr++] = multiplied_poly_to_matrix_row( sht, bht, h, mul, b); mat->nr++; } } static inline void find_multiplied_reducer( bs_t *bs, const hm_t m, len_t *nr, hm_t **rows, ht_t *sht, const md_t * const md ) { len_t i, k; ht_t *bht = bs->ht; const len_t rr = *nr; const len_t evl = bht->evl; const exp_t * const e = sht->ev[m]; const hd_t hdm = sht->hd[m]; const len_t lml = bs->lml; const sdm_t ns = ~hdm.sdm; const sdm_t * const lms = bs->lm; const bl_t * const lmps = bs->lmps; exp_t etmp[bht->evl]; const hd_t * const hdb = bht->hd; exp_t * const * const evb = bht->ev; i = 0; start: while (i < lml && lms[i] & ns) { i++; } if (i < lml) { const hm_t *b = bs->hm[lmps[i]]; const exp_t * const f = evb[b[OFFSET]]; for (k=0; k < evl; ++k) { if (e[k] < f[k]) { i++; goto start; } etmp[k] = (exp_t)(e[k]-f[k]); } const hi_t h = hdm.val - hdb[b[OFFSET]].val; rows[rr] = multiplied_poly_to_matrix_row(sht, bht, h, etmp, b); /* track trace information ? */ if (md->trace_level == LEARN_TRACER) { rows[rr][BINDEX] = lmps[i]; if (bht->eld == bht->esz-1) { enlarge_hash_table(bht); } #if PARALLEL_HASHING rows[rr][MULT] = check_insert_in_hash_table(etmp, h, bht); #else rows[rr][MULT] = insert_in_hash_table(etmp, bht); #endif } sht->hd[m].idx = 2; *nr = rr + 1; } } static void symbolic_preprocessing( mat_t *mat, bs_t *bs, md_t *md ) { hl_t i; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* at the moment we have as many reducers as we have different lcms */ len_t nrr = mat->nc; ht_t *sht = md->ht; /* note that we have already counted the different lcms, i.e. * ncols until this step. moreover, we have also already marked * the corresponding hash indices to represent lead terms. so * we only have to do the bookkeeping for newly added reducers * in the following. */ const hl_t oesld = sht->eld; const len_t onrr = mat->nc; i = 1; /* we only have to check if idx is set for the elements already set * when selecting spairs, afterwards (second for loop) we do not * have to do this check */ while (mat->sz <= nrr + oesld) { mat->sz *= 2; mat->rr = realloc(mat->rr, (unsigned long)mat->sz * sizeof(hm_t *)); } for (; i < oesld; ++i) { if (!sht->hd[i].idx) { sht->hd[i].idx = 1; mat->nc++; find_multiplied_reducer(bs, i, &nrr, mat->rr, sht, md); } } for (; i < sht->eld; ++i) { if (mat->sz == nrr) { mat->sz *= 2; mat->rr = realloc(mat->rr, (unsigned long)mat->sz * sizeof(hm_t *)); } sht->hd[i].idx = 1; mat->nc++; find_multiplied_reducer(bs, i, &nrr, mat->rr, sht, md); } /* realloc to real size */ mat->rr = realloc(mat->rr, (unsigned long)nrr * sizeof(hm_t *)); mat->nr += nrr - onrr; mat->nrl = mat->nr - nrr; mat->nru = nrr; mat->sz = mat->nr; mat->rbal = mat->nrl; /* initialize memory for reducer bit arrays for tracing information */ mat->rba = (rba_t **)malloc((unsigned long)mat->rbal * sizeof(rba_t *)); const unsigned long len = nrr / 32 + ((nrr % 32) != 0); for (i = 0; i < mat->nrl; ++i) { mat->rba[i] = (rba_t *)calloc(len, sizeof(rba_t)); } /* statistics */ md->max_sht_size = md->max_sht_size > sht->esz ? md->max_sht_size : sht->esz; /* timings */ ct1 = cputime(); rt1 = realtime(); md->symbol_ctime += ct1 - ct0; md->symbol_rtime += rt1 - rt0; } static void generate_matrix_from_trace( mat_t *mat, const bs_t * const bs, md_t *md ) { /* timings */ double ct, rt; ct = cputime(); rt = realtime(); len_t i, nr; hm_t *b; exp_t *emul; hi_t h; const len_t idx = md->trace_rd; td_t td = md->tr->td[idx]; ht_t *bht = bs->ht; ht_t *sht = md->ht; mat->rr = (hm_t **)malloc((unsigned long)td.rld * sizeof(hm_t *)); hm_t **rrows = mat->rr; mat->tr = (hm_t **)malloc((unsigned long)td.tld * sizeof(hm_t *)); hm_t **trows = mat->tr; mat->rba = (rba_t **)malloc((unsigned long)td.tld * sizeof(rba_t *)); rba_t **rba = mat->rba; /* reducer rows, i.e. AB part */ i = 0; nr = 0; while (i < td.rld) { b = bs->hm[td.rri[i++]]; emul = bht->ev[td.rri[i]]; h = bht->hd[td.rri[i++]].val; rrows[nr] = multiplied_poly_to_matrix_row(sht, bht, h, emul, b); sht->hd[rrows[nr][OFFSET]].idx = 2; ++nr; } /* to be reduced rows, i.e. CD part */ i = 0; nr = 0; while (i < td.tld) { b = bs->hm[td.tri[i++]]; emul = bht->ev[td.tri[i]]; h = bht->hd[td.tri[i]].val; trows[nr] = multiplied_poly_to_matrix_row(sht, bht, h, emul, b); /* At the moment rba is unused */ rba[nr] = td.rba[i/2]; i++; nr++; } /* meta data for matrix */ mat->nru = td.rld/2; mat->nrl = td.tld/2; mat->nr = mat->sz = mat->nru + mat->nrl; mat->nc = sht->eld-1; /* statistics */ md->max_sht_size = md->max_sht_size > sht->esz ? md->max_sht_size : sht->esz; /* timings */ md->tracer_ctime += cputime() - ct; md->tracer_rtime += realtime() - rt; print_current_trace_meta_data(md); } static void generate_saturation_reducer_rows_from_trace( mat_t *mat, const trace_t * const trace, const len_t idx, const bs_t * const bs, md_t *st, ht_t *sht, const ht_t * const bht ) { /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); len_t i, nr; hm_t *b; exp_t *emul; hi_t h; ts_t ts = trace->ts[idx]; mat->rr = (hm_t **)malloc((unsigned long)ts.rld * sizeof(hm_t *)); hm_t **rrows = mat->rr; /* reducer rows, i.e. AB part */ i = 0; nr = 0; while (i < ts.rld) { b = bs->hm[ts.rri[i++]]; emul = bht->ev[ts.rri[i]]; h = bht->hd[ts.rri[i++]].val; rrows[nr] = multiplied_poly_to_matrix_row(sht, bht, h, emul, b); sht->hd[rrows[nr][OFFSET]].idx = 2; ++nr; } /* meta data for matrix */ mat->nru = ts.rld/2; mat->nr = mat->sz = mat->nru + mat->nrl; mat->nc = sht->eld-1; /* statistics */ st->max_sht_size = st->max_sht_size > sht->esz ? st->max_sht_size : sht->esz; /* timings */ ct1 = cputime(); rt1 = realtime(); st->symbol_ctime += ct1 - ct0; st->symbol_rtime += rt1 - rt0; } static int preprocessing( mat_t *mat, bs_t *bs, md_t *md ) { if (md->trace_level != APPLY_TRACER) { if (select_spairs_by_minimal_degree(mat, bs, md)) { return 1; } symbolic_preprocessing(mat, bs, md); } else { generate_matrix_from_trace(mat, bs, md); } return 0; } msolve-0.6.5/src/neogb/test-driver000077500000000000000000000110431456710632100171120ustar00rootroot00000000000000#! /bin/sh # test-driver - basic testsuite driver script. scriptversion=2018-03-07.03; # UTC # Copyright (C) 2011-2018 Free Software Foundation, Inc. # # 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, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . # Make unconditional expansion of undefined variables an error. This # helps a lot in preventing typo-related bugs. set -u usage_error () { echo "$0: $*" >&2 print_usage >&2 exit 2 } print_usage () { cat <$log_file 2>&1 estatus=$? if test $enable_hard_errors = no && test $estatus -eq 99; then tweaked_estatus=1 else tweaked_estatus=$estatus fi case $tweaked_estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac # Report the test outcome and exit status in the logs, so that one can # know whether the test passed or failed simply by looking at the '.log' # file, without the need of also peaking into the corresponding '.trs' # file (automake bug#11814). echo "$res $test_name (exit status: $estatus)" >>$log_file # Report outcome to console. echo "${col}${res}${std}: $test_name" # Register the test result, and other relevant metadata. echo ":test-result: $res" > $trs_file echo ":global-test-result: $res" >> $trs_file echo ":recheck: $recheck" >> $trs_file echo ":copy-in-global-log: $gcopy" >> $trs_file # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: msolve-0.6.5/src/neogb/tools.c000066400000000000000000000144701456710632100162270ustar00rootroot00000000000000/* This file is part of msolve. * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "tools.h" /* cpu time */ double cputime(void) { double t; t = CLOCKS_PER_SEC / 100000.; t += (double)clock(); return t / CLOCKS_PER_SEC; } /* wall time */ double realtime(void) { struct timeval t; gettimeofday(&t, NULL); t.tv_sec -= (2017 - 1970)*3600*24*365; return (1. + (double)t.tv_usec + ((double)t.tv_sec*1000000.)) / 1000000.; } static void construct_trace( trace_t *trace, mat_t *mat ) { len_t i, j; len_t ctr = 0; const len_t ld = trace->ltd; const len_t nru = mat->nru; const len_t nrl = mat->nrl; rba_t **rba = mat->rba; /* check if there are any non zero new elements, otherwise we * do not need to do this matrix at all in the application steps. */ i = 0; while (i < nrl && mat->tr[i] == NULL) { ++i; } if (i == nrl) { return; } /* non zero new elements exist */ if (trace->ltd == trace->std) { trace->std *= 2; trace->td = realloc(trace->td, (unsigned long)trace->std * sizeof(td_t)); memset(trace->td+trace->std/2, 0, (unsigned long)trace->std/2 * sizeof(td_t)); } const unsigned long lrba = nru / 32 + ((nru % 32) != 0); rba_t *reds = (rba_t *)calloc(lrba, sizeof(rba_t)); for (i = 0; i < nrl; ++i) { if (mat->tr[i] != NULL) { rba[ctr] = rba[i]; ctr++; } else { free(rba[i]); rba[i] = NULL; } } mat->rbal = ctr; mat->rba = rba = realloc(rba, (unsigned long)mat->rbal * sizeof(rba_t *)); const len_t ntr = ctr; /* construct rows to be reduced */ trace->td[ld].tri = realloc(trace->td[ld].tri, (unsigned long)ntr * 2 * sizeof(len_t)); trace->td[ld].tld = 2 * ntr; ctr = 0; for (i = 0; i < nrl; ++i) { if (mat->tr[i] != NULL) { trace->td[ld].tri[ctr++] = mat->tr[i][BINDEX]; trace->td[ld].tri[ctr++] = mat->tr[i][MULT]; } } /* get all needed reducers */ for (i = 0; i < ntr; ++i) { for (j = 0; j < lrba; ++j) { reds[j] |= rba[i][j]; } } /* construct rows to reduce with */ trace->td[ld].rri = realloc(trace->td[ld].rri, (unsigned long)nru * 2 * sizeof(len_t)); trace->td[ld].rld = 2 * nru; ctr = 0; for (i = 0; i < nru; ++i) { if (reds[i/32] >> (i%32) & 1U) { trace->td[ld].rri[ctr++] = mat->rr[i][BINDEX]; trace->td[ld].rri[ctr++] = mat->rr[i][MULT]; } } trace->td[ld].rri = realloc(trace->td[ld].rri, (unsigned long)ctr * sizeof(len_t)); trace->td[ld].rld = ctr; const len_t nrr = ctr; /* new length of rbas, useless reducers removed, * we only need nrr/2 since we do not store the * multipliers in rba */ const unsigned long nlrba = nrr / 2 / 32 + (((nrr / 2) % 32) != 0); /* construct rba information */ trace->td[ld].rba = realloc(trace->td[ld].rba, (unsigned long)ntr * sizeof(rba_t *)); /* allocate memory */ for (i = 0; i < ntr; ++i) { trace->td[ld].rba[i] = calloc(nlrba, sizeof(rba_t)); } ctr = 0; /* write new rbas for tracer with useless reducers removed */ for (i = 0; i < nru; ++i) { if (reds[i/32] >> (i%32) & 1U) { for (j = 0; j < ntr; ++j) { trace->td[ld].rba[j][ctr/32] |= ((rba[j][i/32] >> i%32) & 1U) << ctr%32; } ctr++; } } free(reds); trace->td[ld].deg = mat->cd; } /* Only trace reducer rows for saturation steps to keep * multiplication of saturated elements more flexible. */ static void construct_saturation_trace( trace_t *trace, len_t pos, mat_t *mat ) { len_t i; len_t ctr = 0; const len_t ld = pos; const len_t nru = mat->nru; /* construct rows to reduce with */ trace->ts[ld].rri = realloc(trace->ts[ld].rri, (unsigned long)nru * 2 * sizeof(len_t)); trace->ts[ld].rld = 2 * nru; ctr = 0; for (i = 0; i < nru; ++i) { trace->ts[ld].rri[ctr++] = mat->rr[i][BINDEX]; trace->ts[ld].rri[ctr++] = mat->rr[i][MULT]; } trace->ts[ld].rld = ctr; } static void add_lms_to_trace( trace_t *trace, const bs_t * const bs, const len_t np ) { len_t i; const len_t ld = trace->ltd; trace->td[ld].nlms = realloc(trace->td[ld].nlms, (unsigned long)np * sizeof(hm_t)); for (i = 0; i < np; ++i) { trace->td[ld].nlms[i] = bs->hm[bs->ld + i][OFFSET]; } trace->td[ld].nlm = np; } #if 0 static void add_minimal_lmh_to_trace( trace_t *trace, const bs_t * const bs ) { len_t i; const len_t ld = trace->lts; const len_t lml = bs->lml; /* trace->ts[ld].lmh = realloc(trace->ts[ld].lmh, (unsigned long)lml * sizeof(hm_t)); for (i = 0; i < lml; ++i) { trace->ts[ld].lmh[i] = bs->hm[bs->lmps[i]][OFFSET]; } */ trace->ts[ld].lml = lml; } #endif /* * static inline val_t compare_and_swap( * long *ptr, * long old, * long new * ) * { * val_t prev; * * #if 0 * __asm__ __volatile__( * "lock; cmpxchgl %2, %1" : "=a"(prev), * "+m"(*ptr) : "r"(new), "0"(old) : "memory"); * [> on which systems do we need "cmpxchgq" instead of "cmpxchgl" ? <] * #else * __asm__ __volatile__( * "lock; cmpxchgq %2, %1" : "=a"(prev), * "+m"(*ptr) : "r"(new), "0"(old) : "memory"); * #endif * return prev; * } */ msolve-0.6.5/src/neogb/tools.h000066400000000000000000000046131456710632100162320ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef GB_TOOLS_H #define GB_TOOLS_H #include #include #include "data.h" /* cpu time */ double cputime( void ); /* wall time */ double realtime( void ); static inline uint8_t mod_p_inverse_8( const int16_t val, const int16_t p ) { int16_t a, b, c, d, e, f; a = p; b = val % p; /* if b < 0 we shift correspondingly */ b += (b >> 15) & p; c = 1; d = 0; while (b != 0) { f = b; e = a/f; b = a - e*f; a = f; f = c; c = d - e*f; d = f; } /* if d < 0 we shift correspondingly */ d += (d >> 15) & p; return d; } static inline uint16_t mod_p_inverse_16( const int32_t val, const int32_t p ) { int32_t a, b, c, d, e, f; a = p; b = val % p; /* if b < 0 we shift correspondingly */ b += (b >> 31) & p; c = 1; d = 0; while (b != 0) { f = b; e = a/f; b = a - e*f; a = f; f = c; c = d - e*f; d = f; } /* if d < 0 we shift correspondingly */ d += (d >> 31) & p; return (uint16_t)d; } static inline uint32_t mod_p_inverse_32( const int64_t val, const int64_t p ) { int64_t a, b, c, d, e, f; a = p; b = val % p; /* if b < 0 we shift correspondingly */ b += (b >> 63) & p; c = 1; d = 0; while (b != 0) { f = b; e = a/f; b = a - e*f; a = f; f = c; c = d - e*f; d = f; } /* if d < 0 we shift correspondingly */ d += (d >> 63) & p; return d; } #endif msolve-0.6.5/src/neogb/update.c000066400000000000000000000257731456710632100163610ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "update.h" ps_t *initialize_pairset( void ) { ps_t *ps = (ps_t *)malloc(sizeof(ps_t)); ps->ld = 0; ps->sz = 192; ps->p = (spair_t *)calloc((unsigned long)ps->sz, sizeof(spair_t)); return ps; } static inline void check_enlarge_pairset( ps_t *ps, len_t added ) { if (ps->ld+added >= ps->sz) { ps->sz = ps->sz*2 > ps->ld+added ? ps->sz*2 : ps->ld+added; ps->p = realloc(ps->p, (unsigned long)ps->sz * sizeof(spair_t)); memset(ps->p+ps->ld, 0, (unsigned long)(ps->sz-ps->ld) * sizeof(spair_t)); } } void free_pairset( ps_t **psp ) { ps_t *ps = *psp; if (ps->p) { free(ps->p); ps->p = NULL; ps->ld = 0; ps->sz = 0; } free(ps); ps = NULL; *psp = ps; } static void insert_and_update_spairs( ps_t *psl, bs_t *bs, ht_t *bht, md_t *st ) { int i, j, l; deg_t deg1, deg2; spair_t *ps = psl->p; #ifdef _OPENMP const int nthrds = st->nthrds; #endif const int pl = psl->ld; const int bl = bs->ld; const hm_t nch = bs->hm[bl][OFFSET]; deg_t ndeg = bs->hm[bl][DEG]; bs->mltdeg = bs->mltdeg > ndeg ? bs->mltdeg : ndeg; spair_t *pp = ps+pl; while (bht->esz - bht->eld < bl) { enlarge_hash_table(bht); } #if PARALLEL_HASHING #pragma omp parallel for num_threads(nthrds) \ private(i) #endif for (i = 0; i < bl; ++i) { pp[i].lcm = get_lcm(bs->hm[i][OFFSET], nch, bht, bht); pp[i].gen1 = i; pp[i].gen2 = bl; if (bs->red[i] != 0) { pp[i].deg = -1; } else { if (prime_monomials(bs->hm[pp[i].gen1][OFFSET], bs->hm[pp[i].gen2][OFFSET], bht)) { pp[i].deg = -2; } else { /* compute total degree of pair, not trivial if block order is chosen */ if (st->nev == 0) { pp[i].deg = bht->hd[pp[i].lcm].deg; } else { deg1 = bht->hd[pp[i].lcm].deg - bht->hd[bs->hm[i][OFFSET]].deg + bs->hm[i][DEG]; deg2 = bht->hd[pp[i].lcm].deg - bht->hd[nch].deg + bs->hm[bl][DEG]; pp[i].deg = deg1 > deg2 ? deg1 : deg2; } } } } len_t nl = pl+bl; /* Gebauer-Moeller: check old pairs first */ /* note: old pairs are sorted by the given spair order */ #pragma omp parallel for num_threads(nthrds) \ private(i, j, l) for (i = 0; i < pl; ++i) { j = ps[i].gen1; l = ps[i].gen2; if (pp[j].lcm != ps[i].lcm && pp[l].lcm != ps[i].lcm && pp[j].deg <= ps[i].deg && pp[l].deg <= ps[i].deg && check_monomial_division(ps[i].lcm, nch, bht)) { ps[i].deg = -1; } } /* sort new pairs by increasing lcm, earlier polys coming first */ sort_r(pp, (unsigned long)bl, sizeof(spair_t), spair_cmp_update, bht); /* Gebauer-Moeller: remove real multiples of new spairs */ for (i = pl; i < nl; ++i) { if (ps[i].deg < 0) { continue; } for (j = pl; j < i; ++j) { if (i == j || ps[j].deg == -1) { continue; } if (ps[i].lcm != ps[j].lcm && ps[i].deg >= ps[j].deg && check_monomial_division(ps[i].lcm, ps[j].lcm, bht)) { ps[i].deg = -1; break; } } } /* Gebauer-Moeller: remove same lcm spairs from the new ones */ for (i = pl; i < nl; ++i) { if (ps[i].deg == -1) { continue; } /* try to remove all others if product criterion applies */ if (ps[i].deg == -2) { for (j = pl; j < nl; ++j) { if (ps[j].lcm == ps[i].lcm) { ps[j].deg = -1; } } /* try to eliminate this spair with earlier ones */ } else { for (j = i-1; j >= pl; --j) { if (ps[j].deg != -1 && ps[j].deg <= ps[i].deg && ps[i].lcm == ps[j].lcm) { ps[i].deg = -1; break; } } } } /* remove useless pairs from pairset */ j = 0; /* old pairs */ for (i = 0; i < nl; ++i) { if (ps[i].deg < 0) { continue; } ps[j++] = ps[i]; } psl->ld = j; const bl_t lml = bs->lml; const bl_t * const lmps = bs->lmps; /* mark redundant elements in basis */ deg_t dd = ndeg - bht->hd[nch].deg; if (bs->mltdeg > ndeg) { #if PARALLEL_HASHING #pragma omp parallel for num_threads(nthrds) \ private(i) #endif for (i = 0; i < lml; ++i) { hm_t lm = bs->hm[lmps[i]][OFFSET]; if (bs->red[lmps[i]] == 0 && check_monomial_division(lm, nch, bht) && bs->hm[lmps[i]][DEG]-bht->hd[lm].deg >= dd) { bs->red[lmps[i]] = 1; st->num_redundant++; } } } st->num_gb_crit += nl - psl->ld; bs->ld++; } static void update_lm( bs_t *bs, const ht_t * const bht, md_t *st ) { len_t i, j, k, l; const bl_t * const lmps = bs->lmps; j = bs->lo; nextj: for (; j < bs->ld; ++j) { k = 0; for (l = bs->lo; l < j; ++l) { if (bs->red[l]) { continue; } if (check_monomial_division(bs->hm[j][OFFSET], bs->hm[l][OFFSET], bht)) { bs->red[j] = 1; st->num_redundant++; j++; goto nextj; } } for (i = 0; i < bs->lml; ++i) { if (bs->red[lmps[i]] == 0 && check_monomial_division(bs->hm[lmps[i]][OFFSET], bs->hm[j][OFFSET], bht)) { bs->red[lmps[i]] = 1; st->num_redundant++; } } const sdm_t *lms = bs->lm; for (i = 0; i < bs->lml; ++i) { if (bs->red[lmps[i]] == 0) { bs->lm[k] = lms[i]; bs->lmps[k] = lmps[i]; k++; } } bs->lml = k; k = bs->lml; if (bs->red[j] == 0) { bs->lm[k] = bht->hd[bs->hm[j][OFFSET]].sdm; bs->lmps[k] = j; k++; } bs->lml = k; } bs->lo = bs->ld; st->num_redundant_old = st->num_redundant; } static void update_basis_f4( ps_t *ps, bs_t *bs, ht_t *bht, md_t *st, const len_t npivs ) { len_t i; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* compute number of new pairs we need to handle at most */ len_t np = bs->ld * npivs; for (i = 1; i < npivs; ++i) { np = np + i; } check_enlarge_pairset(ps, np); for (i = 0; i < npivs; ++i) { insert_and_update_spairs(ps, bs, bht, st); } const bl_t lml = bs->lml; const bl_t * const lmps = bs->lmps; len_t k = 0; /* Check new elements on redundancy: * Only elements coming from the same matrix are possible leading * monomial divisors, thus we only check down to bs->lo */ /* #pragma omp parallel for num_threads(st->nthrds) for (int l = bs->lo; l < bs->ld; ++l) { hm_t lm = bs->hm[l][OFFSET]; deg_t dd = bs->hm[l][DEG] - bht->hd[lm].deg; for (int m = bs->lo; m < l; ++m) { if (check_monomial_division(lm, bs->hm[m][OFFSET], bht) == 1 && dd >= (bs->hm[m][DEG] - bht->hd[bs->hm[m][OFFSET]].deg)) { bs->red[l] = 1; st->num_redundant++; break; } } } */ if (st->mo == 0 && st->num_redundant_old < st->num_redundant) { const sdm_t *lms = bs->lm; for (i = 0; i < lml; ++i) { if (bs->red[lmps[i]] == 0) { bs->lm[k] = lms[i]; bs->lmps[k] = lmps[i]; k++; } } bs->lml = k; } k = bs->lml; for (i = bs->lo; i < bs->ld; ++i) { if (bs->red[i] == 0) { bs->lm[k] = bht->hd[bs->hm[i][OFFSET]].sdm; bs->lmps[k] = i; k++; } } bs->lml = k; bs->lo = bs->ld; st->num_redundant_old = st->num_redundant; /* timings */ ct1 = cputime(); rt1 = realtime(); st->update_ctime += ct1 - ct0; st->update_rtime += rt1 - rt0; } static int32_t update( bs_t *bs, md_t *md ) { update_basis_f4(md->ps, bs, bs->ht, md, md->np); if (bs->constant) { return 1; } else { return md->ps->ld == 0; } } /* not needed right now, maybe in a later iteration of sba implementations */ #if 0 static void update_basis_sba_schreyer( ps_t *ps, bs_t *bs, ht_t *bht, ht_t *uht, md_t *st, const len_t npivs ) { len_t i; /* timings */ double ct0, ct1, rt0, rt1; ct0 = cputime(); rt0 = realtime(); /* compute number of new pairs we need to handle at most */ len_t np = bs->ld * npivs; for (i = 1; i < npivs; ++i) { np = np + i; } check_enlarge_pairset(ps, np); for (i = 0; i < npivs; ++i) { insert_and_update_spairs(ps, bs, bht, uht, st); } const bl_t lml = bs->lml; const bl_t * const lmps = bs->lmps; len_t k = 0; if (st->mo == 0 && st->num_redundant_old < st->num_redundant) { const sdm_t *lms = bs->lm; for (i = 0; i < lml; ++i) { if (bs->red[lmps[i]] == 0) { bs->lm[k] = lms[i]; bs->lmps[k] = lmps[i]; k++; } } bs->lml = k; } k = bs->lml; for (i = bs->lo; i < bs->ld; ++i) { if (bs->red[i] == 0) { bs->lm[k] = bht->hd[bs->hm[i][OFFSET]].sdm; j>lmps[k] = i; k++; } } bs->lml = k; bs->lo = bs->ld; st->num_redundant_old = st->num_redundant; /* timings */ ct1 = cputime(); rt1 = realtime(); st->update_ctime += ct1 - ct0; st->update_rtime += rt1 - rt0; } #endif msolve-0.6.5/src/neogb/update.h000066400000000000000000000016221456710632100163510ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef GB_UPDATE_H #define GB_UPDATE_H #include "data.h" ps_t *initialize_pairset( void ); void free_pairset( ps_t **psp ); #endif msolve-0.6.5/src/upolmat/000077500000000000000000000000001456710632100153045ustar00rootroot00000000000000msolve-0.6.5/src/upolmat/nmod_mat_extra.h000066400000000000000000000062521456710632100204630ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Vincent Neiger * Mohab Safey El Din */ /** \file nmod_mat_extra.h * */ #ifndef __NMOD_MAT_EXTRA__H #define __NMOD_MAT_EXTRA__H #include #include #include #ifdef __cplusplus extern "C" { #endif #if __FLINT_VERSION < 3 void nmod_mat_permute_rows(nmod_mat_t mat, const slong * perm_act, slong * perm_store); #endif /** Left nullspace of A. * * Computes a basis X for the left nullspace of A, in reduced row echelon form * with pivots being the rightmost nonzero entries. X should be given * uninitialized, it will be initialized during the call with the right number * of rows. * * This first calls nmod_mat_left_nullspace_compact(), and expands the compact * nullspace representation given by this call into the complete dense * nullspace representation. * * \param [out] X matrix where the nullspace will be stored (uninitialized) * \param [in] A input matrix * \return nullity of A (i.e. rank of X) * * @see nmod_mat_left_nullspace_compact */ FLINT_DLL slong nmod_mat_left_nullspace(nmod_mat_t X, const nmod_mat_t A); /** Left nullspace of A in compact form. * * Computes a basis X for the left nullspace of A, in reduced row echelon form * with pivots being the rightmost nonzero entries. Only the nonpivot columns * of X are stored, in the order they appear in the nullspace basis. The list * permutation contains the concatenation of two lists, each in increasing * order: the positions of the columns without pivots in the rref nullspace * basis, and the positions of the columns with pivots in the rref nullspace * basis (the former being also the row rank profile of A). * * \param [out] X matrix where the nullspace will be stored (uninitialized) * \param [out] permutation list, allocated with A->r elements * \param [in] A input matrix * \return nullity of A (i.e. rank of X) * * \todo efficiency is probably not best for small matrices: this uses Flint's * right nullspace and matrix transposition */ FLINT_DLL slong nmod_mat_left_nullspace_compact( nmod_mat_t X, slong * permutation, const nmod_mat_t A ); #ifdef __cplusplus } #endif #endif // __NMOD_MAT_EXTRA__H /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s msolve-0.6.5/src/upolmat/nmod_mat_left_nullspace.c000066400000000000000000000073231456710632100223330ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Vincent Neiger * Mohab Safey El Din */ #include "nmod_mat_extra.h" #include slong nmod_mat_left_nullspace(nmod_mat_t X, const nmod_mat_t A) { // helper lists of nonpivot|pivot columns of X slong * permutation = flint_malloc(A->r * sizeof(slong)); // compute compact form of left nullspace nmod_mat_t Y; const slong nullity = nmod_mat_left_nullspace_compact(Y,permutation,A); // deduce nullspace const slong rank = A->r - nullity; nmod_mat_init(X, nullity, A->r, A->mod.n); for (slong i = 0; i < nullity; ++i) nmod_mat_entry(X, i, permutation[rank+i]) = 1; for (slong i = 0; i < nullity; ++i) for (slong j = 0; j < rank; ++j) nmod_mat_entry(X, i, permutation[j]) = nmod_mat_entry(Y, i, j); nmod_mat_clear(Y); flint_free(permutation); return nullity; } slong nmod_mat_left_nullspace_compact( nmod_mat_t X, slong * permutation, const nmod_mat_t A ) { // At <- transpose A nmod_mat_t At; nmod_mat_init(At, A->c, A->r, A->mod.n); nmod_mat_transpose(At,A); // Xt <- right kernel of At nmod_mat_t Xt; nmod_mat_init(Xt, At->c, At->c, At->mod.n); slong nullity = nmod_mat_nullspace(Xt, At); const slong rank = At->c - nullity; nmod_mat_init(X, nullity, rank, A->mod.n); if (nullity) { // find row rank profile of A and its complement, store them concatenated // in permutation (first rrp, then complement, each in increasing order) // -> recall: row rank profile = indices of nonpivots in Xt which is in // reduced column echelon form // search pivots first for (slong j = rank; j < At->c; ++j) { permutation[j] = Xt->r - 1; while (permutation[j] >= 0 && nmod_mat_entry(Xt, permutation[j], j-rank) == 0) --permutation[j]; // Note: we should never arrive at (permutation[j] < 0) } slong r = 0; for (slong i = 0; i < permutation[rank]; i++, r++) permutation[r] = i; for (slong j = rank; j < At->c -1; ++j) for (slong i = permutation[j]+1; i < permutation[j+1]; i++, r++) permutation[r] = i; for (slong i = permutation[At->c -1]+1; i < Xt->r; i++, r++) permutation[r] = i; // extract dense part of kernel for (slong i = 0; i < nullity; ++i) for (slong j = 0; j < rank; ++j) nmod_mat_entry(X, i, j) = nmod_mat_entry(Xt, permutation[j], i); } else #if __FLINT_VERSION >= 3 && __FLINT_VERSION_MINOR >= 1 _perm_one(permutation, A->r); #else _perm_set_one(permutation, A->r); #endif // clean nmod_mat_clear(At); nmod_mat_clear(Xt); return nullity; } /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s msolve-0.6.5/src/upolmat/nmod_mat_permute_rows.c000066400000000000000000000043121456710632100220610ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Vincent Neiger * Mohab Safey El Din */ /* The following is a copy-paste from a Flint file added in version 3 */ #if __FLINT_VERSION < 3 /* Copyright (C) 2023 Albin Ahlbäck This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mat_extra.h" /** Permute rows of a matrix `mat` according to `perm_act`, and propagate the * action on `perm_store`. * That is, performs for each appropriate index `i`, the operations * `perm_store[i] <- perm_store[perm_act[i]]` * `rows[i] <- rows[perm_act[i]]` */ void nmod_mat_permute_rows(nmod_mat_t mat, const slong * perm_act, slong * perm_store) { slong i; mp_limb_t ** mat_tmp = (mp_limb_t **) flint_malloc(mat->r * sizeof(mp_limb_t *)); /* perm_store[i] <- perm_store[perm_act[i]] */ if (perm_store) _perm_compose(perm_store, perm_store, perm_act, mat->r); /* rows[i] <- rows[perm_act[i]] */ for (i = 0; i < mat->r; i++) mat_tmp[i] = mat->rows[perm_act[i]]; for (i = 0; i < mat->r; i++) mat->rows[i] = mat_tmp[i]; flint_free(mat_tmp); } #endif // __FLINT_VERSION < 3 /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s msolve-0.6.5/src/upolmat/nmod_mat_poly.h000066400000000000000000000524761456710632100203340ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Vincent Neiger * Mohab Safey El Din */ /** * \file nmod_mat_poly.h * \brief Main header for univariate polynomial with matrix coefficients modulo word-size prime * \version 0.0 * \date 2023-02-13 * * This is the main header for functions for univariate polynomials with * coefficients that are matrices over a finite field Z/pZ for "small" p * (word-size, so that we use a representation with flint's ``nmod``). Only * operations for which this `nmod_mat_poly` format is best suited are * provided. For other operations it is suggested to rely the conversions to and * from `nmod_poly_mat` format and use the relevant functions for that format. * * \todo benchmark performance * \todo more tests for memory leaks * \todo Note: all parameters are supposed init * * \todo transpose, swap/permute rows/cols * \todo set, init_set, swap * \todo init2_mod for init from mod with given alloc * \todo set_trunc, set_shift, attach_trunc, attach_shift * \todo windows? */ #ifdef NMOD_MAT_POLY_INLINES_C #define NMOD_MAT_POLY_INLINE FLINT_DLL #else #define NMOD_MAT_POLY_INLINE static __inline__ #endif #ifndef NMOD_MAT_POLY_H #define NMOD_MAT_POLY_H #include #include #include #ifdef __cplusplus extern "C" { #endif /*------------------------------------------------------------*/ /* struct, typedefs */ /*------------------------------------------------------------*/ /** Struct for matrix polynomials. * * Storage is a dynamic array of matrices `nmod_mat`. The maximum number of * coefficients is `alloc` and the actual number of coefficients (which is the * degree plus 1) is `length`. The number of rows and columns are `r` and `c`. * The modulus is stored as an `nmod_t`. In the provided functions, e.g. for * modifying a coefficient, it is not checked that the dimensions of the * modified coefficient are indeed `r x c`. */ typedef struct { nmod_mat_struct * coeffs; /**< array of coefficients */ slong alloc; /**< allocated length */ slong length; /**< actual length */ slong r; /**< number of rows */ slong c; /**< number of columns */ nmod_t mod; /**< modulus */ } nmod_mat_poly_struct; /** nmod_mat_poly_t allows reference-like semantics for nmod_mat_poly_struct */ typedef nmod_mat_poly_struct nmod_mat_poly_t[1]; /*------------------------------------------------------------*/ /* memory management */ /*------------------------------------------------------------*/ /** @name Memory management for matrix polynomials */ //@{ /** Initialises `matp`. It will have dimensions `r x c` and coefficients modulo * `n`. */ FLINT_DLL void nmod_mat_poly_init(nmod_mat_poly_t matp, slong r, slong c, mp_limb_t n); /** Initialises `matp`. It will have dimensions `r x c` and coefficients modulo * `n`. The caller supplies a precomputed inverse limb generated by * `n_preinvert_limb()`. */ FLINT_DLL void nmod_mat_poly_init_preinv(nmod_mat_poly_t matp, slong r, slong c, mp_limb_t n, mp_limb_t ninv); /** Initialises `matp`. It will have dimensions `r x c` and coefficients modulo * `n`. Up to alloc coefficients may be stored in `matp`. Implementation note: * the `alloc` matrix coefficients are not initialized. */ FLINT_DLL void nmod_mat_poly_init2(nmod_mat_poly_t matp, slong r, slong c, mp_limb_t n, slong alloc); /** Initialises `matp`. It will have dimensions `r x c` and coefficients * modulo~`n`. The caller supplies a precomputed inverse limb generated by * n_preinvert_limb(). Up to alloc coefficients may be stored in `matp`. * Implementation note: the `alloc` matrix coefficients are not initialized. */ FLINT_DLL void nmod_mat_poly_init2_preinv(nmod_mat_poly_t matp, slong r, slong c, mp_limb_t n, mp_limb_t ninv, slong alloc); /** Sets `matp1` to equal `matp2`. It is assumed that these matrices * have identical dimensions and modulus. */ FLINT_DLL void nmod_mat_poly_set(nmod_mat_poly_t matp1, const nmod_mat_poly_t matp2); /** Initialises `matp` using an already initialised modulus `mod`. */ NMOD_MAT_POLY_INLINE void nmod_mat_poly_init_mod(nmod_mat_poly_t matp, slong r, slong c, const nmod_t mod) { matp->coeffs = NULL; matp->alloc = 0; matp->length = 0; matp->r = r; matp->c = c; matp->mod = mod; } /** Set the modulus to `mod`. */ NMOD_MAT_POLY_INLINE void nmod_mat_poly_set_mod(nmod_mat_poly_t matp, const nmod_t mod) { matp->mod = mod; } /** Reallocates `matp` to the given length `alloc`. If the current `length` is * more than `alloc`, the polynomial is truncated and normalised. If `alloc` is * zero, the polynomial is cleared. */ FLINT_DLL void nmod_mat_poly_realloc(nmod_mat_poly_t matp, slong alloc); /** Clears `matp` and releases any memory it used. The matrix polynomial cannot be used again until it is initialised. */ FLINT_DLL void nmod_mat_poly_clear(nmod_mat_poly_t matp); /** Ensures `matp` has space for at least `alloc` coefficients. This function * only ever grows the allocated space, so no data loss can occur. */ FLINT_DLL void nmod_mat_poly_fit_length(nmod_mat_poly_t matp, slong alloc); /** Sets the length of `matp` to `length`. If `length < matp->length` then the * matrix coefficients of `matp` beyond `length` are cleared; otherwise, the * matrix coefficients of `matp` are initialized up to `length`. Note: `matp` * may not be normalized after this. The provided `length` must be less than * `matp->alloc`. */ NMOD_MAT_POLY_INLINE void _nmod_mat_poly_set_length(nmod_mat_poly_t matp, slong length) { if (matp->length > length) for (slong i = length; i < matp->length; i++) nmod_mat_clear(matp->coeffs + i); else for (slong i = matp->length; i < length; i++) nmod_mat_init(matp->coeffs + i, matp->r, matp->c, matp->mod.n); matp->length = length; } /** Normalises a matrix polynomial `matp` so that the top coefficient, if there * is one at all, is not zero. */ NMOD_MAT_POLY_INLINE void _nmod_mat_poly_normalise(nmod_mat_poly_t matp) { while (matp->length && nmod_mat_is_zero(matp->coeffs + matp->length - 1)) { nmod_mat_clear(matp->coeffs + matp->length - 1); matp->length--; } } //@} // doxygen group: Memory management for matrix polynomials /*------------------------------------------------------------*/ /* Zero and Identity */ /*------------------------------------------------------------*/ /** @name Zero and Identity * Functions to set an already initialized matrix polynomial `matp` to zero or * to one (this is the identity matrix if `matp` is square; in general this * puts `1` on the main diagonal and `0` elsewhere). Functions to test whether * a matrix polynomial is zero or one. */ //@{ /** Sets `matp` to the zero matrix polynomial */ NMOD_MAT_POLY_INLINE void nmod_mat_poly_zero(nmod_mat_poly_t matp) { _nmod_mat_poly_set_length(matp, 0); } /** \def nmod_mat_poly_is_zero(matp) * Tests whether `matp` is the zero matrix polynomial */ #define nmod_mat_poly_is_zero(matp) \ ((matp)->length == 0) /** Sets `matp` to the identity matrix polynomial */ NMOD_MAT_POLY_INLINE void nmod_mat_poly_one(nmod_mat_poly_t matp) { nmod_mat_poly_fit_length(matp, 1); _nmod_mat_poly_set_length(matp, 1); nmod_mat_one(matp->coeffs + 0); } /** Tests whether `matp` is one (i.e., if square, the identity matrix * polynomial; otherwise `1` on the main diagonal and `0` elsewhere). */ NMOD_MAT_POLY_INLINE int nmod_mat_poly_is_one(const nmod_mat_poly_t matp) { return (matp->length) == 1 && (nmod_mat_is_one(matp->coeffs + 0)); } //@} // doxygen group: Zero and Identity /*------------------------------------------------------------*/ /* Accessing struct info and coefficients */ /*------------------------------------------------------------*/ /** @name Accessing struct info and matrix coefficients * Get the number of rows, the number of columns, the length, or the degree of * this matrix polynomial. Get a reference to the leading coefficient matrix, * or to the coefficient of degree `k`, or to the entry `i,j` of the * coefficient of degree `k`. Get or set the latter entry. */ //@{ /** Returns the number of rows of `matp`. */ NMOD_MAT_POLY_INLINE slong nmod_mat_poly_nrows(const nmod_mat_poly_t matp) { return matp->r; } /** Returns the number of cols of `matp`. */ NMOD_MAT_POLY_INLINE slong nmod_mat_poly_ncols(const nmod_mat_poly_t matp) { return matp->c; } /** Returns the length of `matp`. */ NMOD_MAT_POLY_INLINE slong nmod_mat_poly_length(const nmod_mat_poly_t matp) { return matp->length; } /** Returns the degree of `matp`. By convention the zero matrix polynomial has * degree `-1`. */ NMOD_MAT_POLY_INLINE slong nmod_mat_poly_degree(const nmod_mat_poly_t matp) { return matp->length - 1; } /** \def nmod_mat_poly_coeff(matp, k) * Returns a reference to the coefficient of degree `k` in the matrix * polynomial `matp`. This function is provided so that individual coefficients * can be accessed and operated on by functions in the `nmod_mat` module. This * function does not make a copy of the data, but returns a reference * `nmod_mat_struct *` to the actual coefficient. Returns `NULL` when `k` * exceeds the degree of the matrix polynomial. */ #define nmod_mat_poly_coeff(matp, k) \ ((k) < (matp)->length ? (matp)->coeffs + (k) : NULL) /** Get the coefficient of degree `k` in the matrix polynomial `matp`. Zeroes * the output matrix when `k` exceeds the degree of the matrix polynomial. */ NMOD_MAT_POLY_INLINE void nmod_mat_poly_get_coeff(nmod_mat_t coeff, const nmod_mat_poly_t matp, slong k) { if (k < matp->length) nmod_mat_set(coeff, matp->coeffs + k); else nmod_mat_zero(coeff); } /** \def nmod_mat_poly_lead(const nmod_mat_poly_t poly) * Returns a reference to the leading coefficient of the matrix polynomial, as * an `nmod_mat_struct *`. This function is provided so that the leading * coefficient can be easily accessed and operated on by functions in the * `nmod_mat` 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. */ #define nmod_mat_poly_lead(matp) \ ((matp)->length ? (matp)->coeffs + (matp)->length - 1 : NULL) /** \def nmod_mat_poly_entry(matp,k,i,j) * Directly accesses the entry in the coefficient of `matp` of degree `k`, 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. */ #define nmod_mat_poly_entry(matp,k,i,j) \ (((matp)->coeffs + (k))->rows[(i)][(j)]) /** Get the entry at row `i` and column `j` in the coefficient of * degree `k` of the matrix polynomial `matp`. */ NMOD_MAT_POLY_INLINE mp_limb_t nmod_mat_poly_get_entry(const nmod_mat_poly_t matp, slong k, slong i, slong j) { return (matp->coeffs + k)->rows[i][j]; } /** Return a pointer to the entry at row `i` and column `j` of the coefficient * of degree `k` of the matrix polynomial `matp` */ NMOD_MAT_POLY_INLINE mp_limb_t * nmod_mat_poly_entry_ptr(const nmod_mat_poly_t matp, slong k, slong i, slong j) { return (matp->coeffs + k)->rows[i] + j; } /** Set to `x` the entry at row `i` and column `j` in the coefficient of degree * `k` of the matrix polynomial `matp`. */ NMOD_MAT_POLY_INLINE void nmod_mat_poly_set_entry(nmod_mat_poly_t matp, slong k, slong i, slong j, mp_limb_t x) { nmod_mat_poly_entry(matp, k, i, j) = x; } //@} // doxygen group: Accessing struct info and matrix coefficients /*------------------------------------------------------------*/ /* Truncate, Shift, Reverse, Permute */ /*------------------------------------------------------------*/ /** @name Truncate, shift, reverse, permute * \todo TODO */ //@{ /** Tests whether `matp` is a constant matrix, that is, of degree 0 */ NMOD_MAT_POLY_INLINE int nmod_mat_poly_is_constant(const nmod_mat_poly_t matp) { return matp->length == 0; } /** Truncates `matp` to the given `order` and normalises it. If `order` is * greater than or equal to the current length of `matp`, then nothing happens. */ NMOD_MAT_POLY_INLINE void nmod_mat_poly_truncate(nmod_mat_poly_t matp, slong order) { if (matp->length > order) { for (slong i = order; i < matp->length; i++) nmod_mat_clear(matp->coeffs + i); matp->length = order; _nmod_mat_poly_normalise(matp); } } /** Sets `(smatp, len + n)` to `(matp, len)` shifted left by `n` coefficients. * Inserts zero coefficients at the lower end. Assumes that `len` and `n` are positive, and that `smatp` fits `len + n` elements. Supports aliasing between res and poly. */ FLINT_DLL void _nmod_mat_poly_shift_left(nmod_mat_struct * smatp, const nmod_mat_struct * matp, slong len, slong n); // TODO //FLINT_DLL void //_nmod_mat_poly_shift_right(nmod_mat_poly_t smatp, // const nmod_mat_poly_t matp, // slong len, // slong n); /** Sets `smatp` to `matp` shifted left by `n` coeffs. Zero coefficients are * inserted. */ FLINT_DLL void nmod_mat_poly_shift_left(nmod_mat_poly_t smatp, const nmod_mat_poly_t matp, slong n); // TODO //FLINT_DLL void //nmod_mat_poly_shift_right(nmod_mat_poly_t smatp, // const nmod_mat_poly_t matp, // slong n); // /** Permute rows of a matrix polynomial `matp` according to `perm_act`, and * propagate the action on `perm_store`. * That is, performs for each appropriate index `i`, the operations * `perm_store[i] <- perm_store[perm_act[i]]` * `rows[i] <- rows[perm_act[i]]` */ NMOD_MAT_POLY_INLINE void nmod_mat_poly_permute_rows(nmod_mat_poly_t matp, const slong * perm_act, slong * perm_store) { slong i; mp_limb_t ** mat_tmp = flint_malloc(matp->r * sizeof(mp_limb_t *)); /* perm_store[i] <- perm_store[perm_act[i]] */ if (perm_store) _perm_compose(perm_store, perm_store, perm_act, matp->r); /* rows[i] <- rows[perm_act[i]] */ for (slong k = 0; k < matp->length; k++) { for (i = 0; i < matp->r; i++) mat_tmp[i] = matp->coeffs[k].rows[perm_act[i]]; for (i = 0; i < matp->r; i++) matp->coeffs[k].rows[i] = mat_tmp[i]; } flint_free(mat_tmp); } //@} // doxygen group: Truncate, shift, reverse, permute /*------------------------------------------------------------*/ /* Intput / Output */ /*------------------------------------------------------------*/ /** @name Input / Output * Printing, writing to a file, reading from a file. * \todo */ //@{ /** Basic print to standard output */ FLINT_DLL void nmod_mat_poly_print(const nmod_mat_poly_t matp); /** Pretty print to standard output */ FLINT_DLL void nmod_mat_poly_print_pretty(const nmod_mat_poly_t matp); //@} // doxygen group: Input / Output /*------------------------------------------------------------*/ /* Basic arithmetic */ /*------------------------------------------------------------*/ /** @name Basic arithmetic * \todo doc */ //@{ /** Compute the coefficient of degree `k` in the product of the two matrix * polynomials. Precisely, if `mat1` is some matrix `A = sum^{deg_A}_{i=0} a_i * x^i` and `mat2` is some matrix `B = sum^{deg_B}_{i=0} b_i x^i`, then `coeff` * will get the coefficient `k` of the product `AB`, which is `c_k = * sum^{i=0}_{k} a_i b_{k-i}`. It is not checked that dimensions or moduli are * compatible. The output `coeff` must already be initialized with dimensions * `mat1->r x mat2->c`. */ FLINT_DLL void nmod_mat_poly_mul_coeff(nmod_mat_t coeff, const nmod_mat_poly_t mat1, const nmod_mat_poly_t mat2, slong k); //@} // doxygen group: Basic arithmetic /*------------------------------------------------------------*/ /*------------------------------------------------------------*/ /* SET FROM CONSTANT OR PMAT */ /*------------------------------------------------------------*/ /*------------------------------------------------------------*/ /** @name Set from constant matrix and polynomial matrix. * * Provides `set` and `init_set`, from either a constant matrix, * or from a `nmod_poly_mat_t`. * * Two main representations are used for polynomial matrices: * - a polynomial matrix stored as a matrix with polynomial entries, that * is, of type `nmod_poly_mat_t` * - a polynomial matrix stored as a polynomial with matrix coefficients, * that is, of type `nmod_mat_poly_t` * * The following functions perform conversions between these types, with two * variants: either the degree is deduced from the input, or a user-provided * truncation order is used. * * \todo init-set variants */ //@{ /** Initialize a polynomial matrix `pmat` of the same dimensions and modulus as * a constant matrix `mat`, and set its constant coefficient to `mat`. * \todo to be written * careful: probably better to use nmod_poly_init with preinv... * but this should have been done in Flint's native poly_mat_init too? **/ FLINT_DLL void nmod_mat_poly_init_set_from_nmod_mat(nmod_mat_poly_t matp, const nmod_mat_t cmat); /** Set the polynomial matrix `pmat` to be a constant polynomial matrix whose * constant coefficient is a copy of `cmat`. This assumes `pmat` is already * initialized with the same modulus and dimensions as `cmat`. */ FLINT_DLL void nmod_mat_poly_set_from_nmod_mat(nmod_mat_poly_t matp, const nmod_mat_t cmat); /** Set from polynomial with matrix coefficients `matp`, truncated at the * specified `order` (a nonnegative integer). */ FLINT_DLL void nmod_mat_poly_set_trunc_from_poly_mat(nmod_mat_poly_t matp, const nmod_poly_mat_t pmat, slong order); /** Set from polynomial with matrix coefficients `matp`. */ // TODO benchmark and try variants if needed NMOD_MAT_POLY_INLINE void nmod_mat_poly_set_from_poly_mat(nmod_mat_poly_t matp, const nmod_poly_mat_t pmat) { nmod_mat_poly_set_trunc_from_poly_mat(matp, pmat, nmod_poly_mat_max_length(pmat)); } //@} // doxygen group: Conversion from constant matrix and polynomial matrix /** @name M-Basis algorithm (uniform approximant order) * \anchor mbasis * * See .nmod_poly_mat_approximant.h for general definitions and conventions * about approximant bases in PML. * * The functions here compute a `shift`-minimal ordered weak Popov approximant * basis for `(pmat,orders)` in the case where `orders` is given by a single * integer `orders = (order,...order)`. They iterate from `1` to `order`, * computing at each step a basis at order `1` (see @ref mbasis1) and using it * to update the output `appbas`, the so-called _residual matrix_, and the * considered shift. At step `d`, we have `appbas*pmat = 0 mod x^{d-1}`, and we * want to update `appbas` so that this becomes zero modulo `x^d`. * * In this context, the residual matrix is a constant matrix with the same * dimensions as `pmat` which, at the iteration `d`, is equal to the * coefficient of degree `d` of `appbas*pmat` (the coefficients of lower degree * being already zero). * * At the end of the computation, the vector `shift` contains the shifted row * degree of `appbas`, for the input shift. * * This is inspired from the algorithm _mbasis_ described in * - P. Giorgi, C.-P. Jeannerod, G. Villard. Proceeding ISSAC 2003, * - P. Giorgi, R. Lebreton. Proceedings ISSAC 2014. */ //@{ /** Main mbasis function. */ FLINT_DLL void nmod_mat_poly_mbasis(nmod_mat_poly_t appbas, slong * shift, const nmod_mat_poly_t matp, slong order); //@} // doxygen group: M-Basis algorithm (uniform approximant order) #ifdef __cplusplus } #endif #endif /* NMOD_MAT_POLY_H */ /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s msolve-0.6.5/src/upolmat/nmod_mat_poly_arith.c000066400000000000000000000042641456710632100215060ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Vincent Neiger * Mohab Safey El Din */ #include #include "nmod_mat_poly.h" void nmod_mat_poly_mul_coeff(nmod_mat_t coeff, const nmod_mat_poly_t mat1, const nmod_mat_poly_t mat2, slong k) { // only consider indices i such that: // 0 <= i <= k // i < mat1->length // k-i < mat2->length // so i < min(k+1,mat1->length) // and i >= max(0, k + 1 - mat2->length) const slong ubound = FLINT_MIN(k+1, mat1->length); const slong lbound = FLINT_MAX(0, k+1 - mat2->length); // lbound >= ubound ==> coeff is zero, no term to consider if (lbound >= ubound) { nmod_mat_zero(coeff); return; } // now lbound < ubound // first handle i == lbound separately, to avoid wasting time zero-ing `coeff` nmod_mat_mul(coeff, mat1->coeffs + lbound, mat2->coeffs + (k - lbound)); // `if` just here to avoid initializing temp for nothing if (lbound + 1 < ubound) { nmod_mat_t temp; nmod_mat_init(temp, mat1->r, mat2->c, mat1->mod.n); for (slong i = lbound+1; i < ubound; i++) { nmod_mat_mul(temp, mat1->coeffs + i, mat2->coeffs + (k - i)); nmod_mat_add(coeff, coeff, temp); } nmod_mat_clear(temp); } } /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s msolve-0.6.5/src/upolmat/nmod_mat_poly_io.c000066400000000000000000000025441456710632100210050ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Vincent Neiger * Mohab Safey El Din */ #include "nmod_mat_poly.h" void nmod_mat_poly_print(const nmod_mat_poly_t matp) { for (slong i = 0; i < matp->length; i++) nmod_mat_print(matp->coeffs + i); } void nmod_mat_poly_print_pretty(const nmod_mat_poly_t matp) { printf("r: %ld, c: %ld, len: %ld, mod: %ld\n", matp->r, matp->c, matp->length, matp->mod.n); for (slong i = 0; i < matp->length; i++) { printf("coeff %ld:\n", i); nmod_mat_print_pretty(matp->coeffs + i); } } /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s msolve-0.6.5/src/upolmat/nmod_mat_poly_mbasis.c000066400000000000000000000357651456710632100216670ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Vincent Neiger * Mohab Safey El Din */ #include // for qsort #include #include #include #include #include "nmod_mat_poly.h" #include "nmod_mat_extra.h" //#define MBASIS1_PROFILE //#define MBASIS_PROFILE //#define PMBASIS_PROFILE //#define MBASIS_DEBUG #ifdef MBASIS_PROFILE #define _MBASIS_PROFILER_INIT \ timeit_t t_others,t_residual,t_appbas,t_kernel,t_now; \ t_others->cpu = 0; t_others->wall = 0; \ t_residual->cpu = 0; t_residual->wall = 0; \ t_appbas->cpu = 0; t_appbas->wall = 0; \ t_kernel->cpu = 0; t_kernel->wall = 0; #define _PROFILER_REGION_START timeit_start(t_now); #define _PROFILER_REGION_STOP(_counter_) \ timeit_stop(t_now); \ (_counter_)->cpu += t_now->cpu; \ (_counter_)->wall += t_now->wall; #define _MBASIS_PROFILER_OUTPUT \ double total_cpu = t_others->cpu + t_residual->cpu + \ t_appbas->cpu + t_kernel->cpu; \ double total_wall = t_others->wall + t_residual->wall + \ t_appbas->wall + t_kernel->wall; \ printf("wall\tothers\t\tresidual\tappbas\t\tkernel\n"); \ printf("\t%f\t%f\t%f\t%f\n", \ 100 * t_others->wall / total_wall, \ 100 * t_residual->wall / total_wall, \ 100 * t_appbas->wall / total_wall, \ 100 * t_kernel->wall / total_wall); \ printf("cpu\tothers\t\tresidual\tappbas\t\tkernel\n"); \ printf("\t%f\t%f\t%f\t%f\n", \ 100 * t_others->cpu / total_cpu, \ 100 * t_residual->cpu / total_cpu, \ 100 * t_appbas->cpu / total_cpu, \ 100 * t_kernel->cpu / total_cpu); \ printf("\t%ld\t%ld\t%ld\t%ld\n", \ t_others->wall, \ t_residual->wall, \ t_appbas->wall, \ t_kernel->wall); \ #else // MBASIS_PROFILE #define _MBASIS_PROFILER_INIT #define _PROFILER_REGION_START #define _PROFILER_REGION_STOP(_counter_) #define _MBASIS_PROFILER_OUTPUT #endif // MBASIS_PROFILE /* type for stable sort while retaining the permutation */ typedef struct { slong value; slong index; } slong_pair; /* comparator for quicksort, lexicographic (total) order to ensure stable sort */ static inline int _slong_pair_compare(const void * a, const void * b) { slong_pair aa = * (const slong_pair *) a; slong_pair bb = * (const slong_pair *) b; if (aa.value == bb.value) { if (aa.index < bb.index) return -1; else if (aa.index > bb.index) return 1; else // aa.index == bb.index return 0; } else if (aa.value < bb.value) return -1; else // aa.value > bb.value return 1; } /** Creates a permutation from the sorting of a shift * After running this, perm is the unique list of integers which sorts * the pairs (shift,index) increasingly, i.e. * shift[perm[0]] <= shift[perm[1]] < ... < shift[perm[n-1]] * * \param perm permutation (list of integers), length n * \param shift list of integer to be sorted nondecreasingly, length n * \param pair_tmp temporary storage, length n * \param n length * */ static inline void _find_shift_permutation(slong * perm, const slong * shift, slong n, slong_pair * pair_tmp) { for (slong i = 0; i < n; i++) { pair_tmp[i].value = shift[i]; pair_tmp[i].index = i; } qsort(pair_tmp, n, sizeof(slong_pair), _slong_pair_compare); for (slong i = 0; i < n; i++) perm[i] = pair_tmp[i].index; } void nmod_mat_poly_mbasis(nmod_mat_poly_t appbas, slong * shift, const nmod_mat_poly_t matp, slong order) { _MBASIS_PROFILER_INIT _PROFILER_REGION_START // dimensions of input matrix const slong m = matp->r; const slong n = matp->c; // initialize output approximant basis with identity // except when matp == 0: return appbas = x**order * identity if (nmod_mat_poly_is_zero(matp)) { nmod_mat_poly_fit_length(appbas, order+1); _nmod_mat_poly_set_length(appbas, order+1); nmod_mat_one(appbas->coeffs + order); _PROFILER_REGION_STOP(t_others) _MBASIS_PROFILER_OUTPUT return; } else nmod_mat_poly_one(appbas); // -> ensures matp->length > 0 in what follows // residual matrix: m x n constant matrix, next coefficient of appbas * // matp to be annihilated nmod_mat_t res; nmod_mat_init(res, m, n, matp->mod.n); // temporary matrix used during the computation of residuals nmod_mat_t res_tmp; nmod_mat_init(res_tmp, m, n, res->mod.n); // will hold the stable permutation making the shift nondecreasing slong * perm = _perm_init(m); slong_pair * pair_tmp = (slong_pair *) flint_malloc(m * sizeof(slong_pair)); // to store the left constant nullspace bases, their ranks, // and corresponding pivot information slong nullity; slong * pivots = (slong *) flint_malloc(m * sizeof(slong)); nmod_mat_t nsbas; _PROFILER_REGION_STOP(t_others) // Note: iterations will guarantee that `shift` (initially, this is the // input shift) holds the `shift`-shifted row degree of appbas; in // particular this is the case when the algorithm returns for (slong ord = 0; ord < order; ++ord) { #ifdef MBASIS_DEBUG printf("\n\nDEBUG -- Start iteration %ld\n", ord); #endif // MBASIS_DEBUG _PROFILER_REGION_START // Letting s0 be the original input shift: // start of loop: appbas is an `s0`-ordered weak Popov approximant // basis at order `ord` for `pmat`, and shift = rdeg_s0(appbas) // end of loop: appbas is an `s0`-ordered weak Popov approximant // basis at order `ord+1` for `pmat`, and shift = rdeg_s0(appbas) if (ord == 0) // initially res = coeffs_matp[0] (note matp->length > 0 here) nmod_mat_set(res, matp->coeffs + 0); else // res = coefficient of degree ord in appbas*pmat nmod_mat_poly_mul_coeff(res, appbas, matp, ord); // TODO try another variant with res_tmp to save memory? _PROFILER_REGION_STOP(t_residual) _PROFILER_REGION_START // compute stable permutation which makes the shift nondecreasing // --> we will need to permute things, to take into account the // "priority" indicated by the shift _find_shift_permutation(perm, shift, m, pair_tmp); #ifdef MBASIS_DEBUG printf("\n\nDEBUG -- it %ld -- shift: ", ord); _perm_print(shift, m); printf("\n\nDEBUG -- it %ld -- permutation: ", ord); _perm_print(perm, m); #endif // MBASIS_DEBUG // permute rows of the residual accordingly #ifdef MBASIS_DEBUG printf("\n\nDEBUG -- it %ld -- res before perm: ", ord); nmod_mat_print_pretty(res); #endif // MBASIS_DEBUG nmod_mat_permute_rows(res, perm, NULL); #ifdef MBASIS_DEBUG printf("\n\nDEBUG -- it %ld -- res after perm: ", ord); nmod_mat_print_pretty(res); #endif // MBASIS_DEBUG _PROFILER_REGION_STOP(t_others) _PROFILER_REGION_START // find the left nullspace basis of the (permuted) residual, in reduced // row echelon form and compact storage (see the documentation) if (ord >= 1) // nsbas should be uninitialized for nullspace nmod_mat_clear(nsbas); nullity = nmod_mat_left_nullspace_compact(nsbas,pivots,res); _PROFILER_REGION_STOP(t_kernel) #ifdef MBASIS_DEBUG printf("\n\nDEBUG -- it %ld -- nullity: %ld, rank: %ld", ord, nullity, m-nullity); printf("\n\nDEBUG -- it %ld -- nsbas: ", ord); nmod_mat_print_pretty(nsbas); printf("\n\nDEBUG -- it %ld -- pivots: ", ord); _perm_print(pivots, m); #endif // MBASIS_DEBUG if (nullity==0) { // Exceptional case: the residual matrix has empty left nullspace // --> no need to compute more: the final basis is X^(order-ord)*appbas _PROFILER_REGION_START nmod_mat_poly_shift_left(appbas, appbas, order-ord); for (long i = 0; i < m; ++i) shift[i] += order-ord; _PROFILER_REGION_STOP(t_others) break; } else if (nullity < m) { // nothing to do if nullity == m, another exceptional case: // residual coeff was zero, and nullspace 'nsbas' is identity // --> approximant basis is already correct for this order, no need to // change it or to change shift, go to next iteration // here, we are in the "usual" case, where the left nullspace of the // residual has no special shape // things will be easier in the permuted world, gathering pivot // rows and non-pivot rows // --> we are currently working on perm * appbas // i.e. perm*appbas[i] = appbas[perm[i]] // --> we will add to this the pivot permutation: // i.e. pivots*perm*appbas[i] = appbas[perm[pivots[i]]] _PROFILER_REGION_START // transform pivots[i] into perm[pivots[i]] _perm_compose(pivots, perm, pivots, m); #ifdef MBASIS_DEBUG printf("\n\nDEBUG -- it %ld -- composed permutation: ", ord); _perm_print(pivots, m); #endif // MBASIS_DEBUG // Update the shift // --> in the permuted world, we should add 1 to each entry // corresponding to a nullspace column which contains a pivot // (don't move below! pivots will be modified) #ifdef MBASIS_DEBUG printf("\n\nDEBUG -- it %ld -- shift before update: ", ord); _perm_print(shift, m); #endif // MBASIS_DEBUG for (slong i = 0; i < m-nullity; i++) shift[pivots[i]] += 1; #ifdef MBASIS_DEBUG printf("\n\nDEBUG -- it %ld -- shift after update: ", ord); _perm_print(shift, m); #endif // MBASIS_DEBUG // Update the approximant basis: 1/ go to permuted world #ifdef MBASIS_DEBUG printf("\n\nDEBUG -- it %ld -- appbas before update:\n", ord); nmod_mat_poly_print_pretty(appbas); #endif // MBASIS_DEBUG nmod_mat_poly_permute_rows(appbas, pivots, NULL); #ifdef MBASIS_DEBUG printf("\n\nDEBUG -- it %ld -- permuted appbas before update:\n", ord); nmod_mat_poly_print_pretty(appbas); #endif // MBASIS_DEBUG _PROFILER_REGION_STOP(t_others) _PROFILER_REGION_START // Update the approximant basis: 2/ perform constant update // Submatrix of rows corresponding to pivots are replaced by // nsbas*appbas (note: these rows currently have degree // at most deg(appbas)) // FIXME possible small improvement for uniform shift: these rows // have degree less than deg(appbas), in this case (and deg(appbas) // is reached on the diagonal, among the pivot degrees) // TODO see if a convenient way to make this matrix fixed at the beginning; // note nullity is most often unchanged along iterations // TODO generally try to improve memory handling in here nmod_mat_t ns_app, app_win_mul, app_win_add; nmod_mat_init(ns_app, nullity, appbas->c, appbas->mod.n); for (slong d = 0; d < appbas->length; ++d) { nmod_mat_window_init(app_win_mul, appbas->coeffs + d, 0, 0, m-nullity, m); nmod_mat_window_init(app_win_add, appbas->coeffs + d, m-nullity, 0, m, m); nmod_mat_mul(ns_app, nsbas, app_win_mul); nmod_mat_add(app_win_add, app_win_add, ns_app); } nmod_mat_clear(ns_app); nmod_mat_clear(app_win_mul); nmod_mat_clear(app_win_add); // Update the approximant basis: 3/ left-shift relevant rows by 1 // increase length of appbas if necessary for (slong i = 0; i < m-nullity; ++i) if (!_nmod_vec_is_zero(appbas->coeffs[appbas->length-1].rows[i], m)) { nmod_mat_poly_fit_length(appbas, appbas->length+1); _nmod_mat_poly_set_length(appbas, appbas->length+1); i = m - nullity; } // rows not corresponding to pivots are multiplied by X // note: these rows currently have length strictly less than len(appbas) mp_limb_t ** save_zero_rows = (mp_limb_t **) flint_malloc((m-nullity) * sizeof(mp_limb_t *)); for (slong i = 0; i < m-nullity; ++i) { save_zero_rows[i] = appbas->coeffs[appbas->length-1].rows[i]; appbas->coeffs[appbas->length-1].rows[i] = appbas->coeffs[appbas->length-2].rows[i]; // note: arrived at this stage, appbas->length must be >= 2 } for (slong d = appbas->length-2; d > 0; d--) for (slong i = 0; i < m-nullity; ++i) appbas->coeffs[d].rows[i] = appbas->coeffs[d-1].rows[i]; for (slong i = 0; i < m-nullity; ++i) //_nmod_vec_zero(appbas->coeffs[0].rows[i], m); appbas->coeffs[0].rows[i] = save_zero_rows[i]; _PROFILER_REGION_STOP(t_appbas) _PROFILER_REGION_START #ifdef MBASIS_DEBUG printf("\n\nDEBUG -- it %ld -- permuted appbas after update:\n", ord); nmod_mat_poly_print_pretty(appbas); #endif // MBASIS_DEBUG // Update the approximant basis: 4/ come back from permuted world _perm_inv(pivots, pivots, m); #ifdef MBASIS_DEBUG printf("\n\nDEBUG -- it %ld -- inverted composed permutation: ", ord); _perm_print(pivots, m); #endif // MBASIS_DEBUG nmod_mat_poly_permute_rows(appbas, pivots, NULL); #ifdef MBASIS_DEBUG printf("\n\nDEBUG -- it %ld -- appbas after update:\n", ord); nmod_mat_poly_print_pretty(appbas); #endif // MBASIS_DEBUG _PROFILER_REGION_STOP(t_others) } } _PROFILER_REGION_START nmod_mat_clear(res); nmod_mat_clear(res_tmp); _perm_clear(perm); flint_free(pair_tmp); flint_free(pivots); nmod_mat_clear(nsbas); _PROFILER_REGION_STOP(t_others) _MBASIS_PROFILER_OUTPUT return; } /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s msolve-0.6.5/src/upolmat/nmod_mat_poly_mem.c000066400000000000000000000117571456710632100211620ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Vincent Neiger * Mohab Safey El Din */ #include "flint/ulong_extras.h" // for n_preinvert_limb #include "nmod_mat_poly.h" /*------------------------------------------------------------*/ /*------------------------------------------------------------*/ /* INIT */ /*------------------------------------------------------------*/ /*------------------------------------------------------------*/ void nmod_mat_poly_init_preinv(nmod_mat_poly_t matp, slong r, slong c, mp_limb_t n, mp_limb_t ninv) { matp->coeffs = NULL; matp->alloc = 0; matp->length = 0; matp->r = r; matp->c = c; matp->mod.n = n; matp->mod.ninv = ninv; #if __FLINT_VERSION < 3 count_leading_zeros(matp->mod.norm, n); #else matp->mod.norm = flint_clz(n); #endif } void nmod_mat_poly_init(nmod_mat_poly_t matp, slong r, slong c, mp_limb_t n) { nmod_mat_poly_init_preinv(matp, r, c, n, n_preinvert_limb(n)); } void nmod_mat_poly_init2_preinv(nmod_mat_poly_t matp, slong r, slong c, mp_limb_t n, mp_limb_t ninv, slong alloc) { if (alloc) matp->coeffs = (nmod_mat_struct *) flint_malloc(alloc * sizeof(nmod_mat_struct)); else matp->coeffs = NULL; matp->alloc = alloc; matp->length = 0; matp->r = r; matp->c = c; matp->mod.n = n; matp->mod.ninv = ninv; #if __FLINT_VERSION < 3 count_leading_zeros(matp->mod.norm, n); #else matp->mod.norm = flint_clz(n); #endif } void nmod_mat_poly_init2(nmod_mat_poly_t matp, slong r, slong c, mp_limb_t n, slong alloc) { nmod_mat_poly_init2_preinv(matp, r, c, n, n_preinvert_limb(n), alloc); } /*------------------------------------------------------------*/ /* SET / INIT SET */ /*------------------------------------------------------------*/ void nmod_mat_poly_set(nmod_mat_poly_t matp1, const nmod_mat_poly_t matp2) { if (matp1 != matp2) /* Aliasing is trivial */ { const slong len = matp2->length; nmod_mat_poly_fit_length(matp1, len); _nmod_mat_poly_set_length(matp1, len); for (slong i = 0; i < len; i++) nmod_mat_set(matp1->coeffs + i, matp2->coeffs + i); } } /*------------------------------------------------------------*/ /*------------------------------------------------------------*/ /* CLEAR / REALLOC / FIT LENGTH */ /*------------------------------------------------------------*/ /*------------------------------------------------------------*/ void nmod_mat_poly_clear(nmod_mat_poly_t matp) { // clear any allocated matrix coefficient for (slong i=0; i < matp->length; i++) nmod_mat_clear(matp->coeffs + i); // free coeffs if (matp->coeffs) flint_free(matp->coeffs); } void nmod_mat_poly_realloc(nmod_mat_poly_t matp, slong alloc) { // clear and set to 0 if (alloc == 0) { nmod_mat_poly_clear(matp); matp->length = 0; matp->alloc = 0; matp->coeffs = NULL; return; } if (matp->alloc) // realloc { // truncate at order `alloc` nmod_mat_poly_truncate(matp, alloc); matp->coeffs = (nmod_mat_struct *) flint_realloc(matp->coeffs, alloc * sizeof(nmod_mat_struct)); } else // not allocated yet, do it now matp->coeffs = (nmod_mat_struct *) flint_malloc(alloc * sizeof(nmod_mat_struct)); matp->alloc = alloc; } void nmod_mat_poly_fit_length(nmod_mat_poly_t matp, slong alloc) { // realloc to the maximum of `alloc` and // the double of the current `matp->alloc` if (alloc > matp->alloc) { if (alloc < 2 * matp->alloc) alloc = 2 * matp->alloc; nmod_mat_poly_realloc(matp, alloc); } } /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s msolve-0.6.5/src/upolmat/nmod_mat_poly_set_from.c000066400000000000000000000047351456710632100222200ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Vincent Neiger * Mohab Safey El Din */ #include "nmod_mat_poly.h" #include void nmod_mat_poly_init_set_from_nmod_mat(nmod_mat_poly_t matp, const nmod_mat_t cmat) { nmod_mat_poly_init2_preinv(matp, cmat->r, cmat->c, cmat->mod.n, cmat->mod.ninv, 1); // if cmat is zero: do nothing more // otherwise set length to 1 and copy data if (! nmod_mat_is_zero(cmat)) { nmod_mat_init_set(matp->coeffs + 0, cmat); matp->length = 1; } } void nmod_mat_poly_set_from_nmod_mat(nmod_mat_poly_t matp, const nmod_mat_t cmat) { if (nmod_mat_is_zero(cmat)) nmod_mat_poly_zero(matp); else { nmod_mat_poly_fit_length(matp, 1); _nmod_mat_poly_set_length(matp, 1); nmod_mat_set(matp->coeffs + 0, cmat); } } void nmod_mat_poly_set_trunc_from_poly_mat(nmod_mat_poly_t matp, const nmod_poly_mat_t pmat, slong order) { const slong len = nmod_poly_mat_max_length(pmat); if (order > len) order = len; // allocate and init coefficients nmod_mat_poly_fit_length(matp, order); _nmod_mat_poly_set_length(matp, order); // fill data for (slong k = 0; k < order; k++) for (slong i = 0; i < matp->r; i++) for (slong j = 0; j < matp->c; j++) nmod_mat_poly_entry(matp, k, i, j) = nmod_poly_get_coeff_ui(nmod_poly_mat_entry(pmat, i, j), k); // normalize (useless if order==len) if (order < len) _nmod_mat_poly_normalise(matp); } /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s msolve-0.6.5/src/upolmat/nmod_mat_poly_shift.c000066400000000000000000000045711456710632100215150ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Vincent Neiger * Mohab Safey El Din */ #include "nmod_mat_poly.h" void _nmod_mat_poly_shift_left(nmod_mat_struct * smatp, const nmod_mat_struct * matp, slong len, slong n) { if (smatp != matp) { for (slong i = 0; i < len; i++) nmod_mat_set(smatp + n + i, matp + i); } else { /* Copy in reverse to avoid writing over unshifted coefficients */ for (slong i = len-1; i >= 0; i--) nmod_mat_swap(smatp + n + i, smatp + i); } for (slong i = 0; i < n; i++) nmod_mat_zero(smatp + i); } //void _nmod_mat_poly_shift_right(nmod_mat_poly_t smatp, // const nmod_mat_poly_t matp, // slong len, // slong n) //{ //} void nmod_mat_poly_shift_left(nmod_mat_poly_t smatp, const nmod_mat_poly_t matp, slong n) { if (n == 0) { nmod_mat_poly_set(smatp, matp); return; } if (matp->length == 0) { nmod_mat_poly_zero(smatp); return; } nmod_mat_poly_fit_length(smatp, matp->length + n); _nmod_mat_poly_set_length(smatp, matp->length + n); _nmod_mat_poly_shift_left(smatp->coeffs, matp->coeffs, matp->length - n, n); } //void nmod_mat_poly_shift_right(nmod_mat_poly_t smatp, // const nmod_mat_poly_t matp, // slong n); /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s msolve-0.6.5/src/upolmat/nmod_poly_mat_pmbasis.c000066400000000000000000000050201456710632100220240ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Vincent Neiger * Mohab Safey El Din */ #include "nmod_mat_poly.h" // truncate, shift, middle_product #include "nmod_poly_mat_utils.h" // truncate, shift, middle_product #include "nmod_poly_mat_pmbasis.h" void nmod_poly_mat_mbasis(nmod_poly_mat_t appbas, slong * shift, const nmod_poly_mat_t pmat, ulong order) { nmod_mat_poly_t app, matp; nmod_mat_poly_init(matp, pmat->r, pmat->c, pmat->modulus); // TODO improve: set init nmod_mat_poly_set_trunc_from_poly_mat(matp, pmat, order); nmod_mat_poly_init(app, pmat->r, pmat->r, pmat->modulus); nmod_mat_poly_mbasis(app, shift, matp, order); // TODO improve: set init nmod_poly_mat_set_from_mat_poly(appbas, app); nmod_mat_poly_clear(matp); nmod_mat_poly_clear(app); } void nmod_poly_mat_pmbasis(nmod_poly_mat_t appbas, slong * shift, const nmod_poly_mat_t pmat, slong order) { if (order <= PMBASIS_THRES) { nmod_poly_mat_mbasis(appbas, shift, pmat, order); return; } const long order1 = order>>1; const long order2 = order - order1; nmod_poly_mat_t appbas2, residual; nmod_poly_mat_init(appbas2, pmat->r, pmat->r, pmat->modulus); nmod_poly_mat_init(residual, pmat->r, pmat->c, pmat->modulus); nmod_poly_mat_pmbasis(appbas, shift, pmat, order1); nmod_poly_mat_middle_product(residual, appbas, pmat, order1, order); nmod_poly_mat_pmbasis(appbas2, shift, residual, order2); nmod_poly_mat_mul(appbas, appbas2, appbas); nmod_poly_mat_clear(appbas2); nmod_poly_mat_clear(residual); } /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s msolve-0.6.5/src/upolmat/nmod_poly_mat_pmbasis.h000066400000000000000000000125301456710632100220350ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Vincent Neiger * Mohab Safey El Din */ /** * \file nmod_poly_mat_approximant.h * \brief Minimal approximant bases * */ /** \file nmod_poly_mat_approximant.h * Definition (approximant basis). * ------------------------------- * Consider: * - an m x n matrix of univariate polynomials F, * - an approximation order d (list of n positive integers). * * Then an approximant basis for (F,d) is a matrix over the univariate * polynomials whose rows form a basis for the following module: * { p in K[X]^{1 x m} | the column j of p F is 0 modulo X^{d[j]} }. * Note that such a matrix is square, m x m, and nonsingular. Its determinant * has the form X^k for some 0 <= k <= d[0] + d[1] + .. + d[n-1]. */ /** \file nmod_poly_mat_approximant.h * Definition (shifted minimal approximant basis). * ----------------------------------------------- * Starting from the definition of an approximant basis, consider further: * - a degree shift s (a list of m integers). * * Then an approximant basis for (F,d) is said to be a shift-minimal * (resp. a shift-ordered weak Popov, resp. the shift-Popov) * approximant basis if it is in shift-reduced form (resp. in shift-ordered * weak Popov form, resp. in shift-Popov form). See nmod_poly_mat_forms.h * for definitions of these forms. */ /** \file nmod_poly_mat_approximant.h * Conventions. * ------------ * Apart from the general interfaces (TODO) which offer the choice between left or * right approximants, all other functions compute left approximant bases * (approximants operate on the left of the matrix F; the basis elements are * the rows of the matrix). * * Most functions below use the following parameters. * * \param[out] appbas the output approximant basis (cannot alias `pmat`) * \param[in] pmat the input polynomial matrix (no restriction) * \param[in] order the input order (list of strictly positive integers, length must be the number of columns of `pmat`) * \param[in,out] shift in: the input shift; and out: the output shifted row degree of `appbas` (list of integers, length must be the number of rows of `pmat`) * * Note that the latter two restrictions on the lengths of the lists are * assuming left approximants; for right approximants, they are swapped. */ #ifndef NMOD_POLY_MAT_APPROXIMANT_H #define NMOD_POLY_MAT_APPROXIMANT_H #define PMBASIS_THRES 32 #include #ifdef __cplusplus extern "C" { #endif /** @name M-Basis algorithm (uniform approximant order) * * The core of these functions is implemented with `nmod_mat_poly_t` type, * for efficiency reasons. The bulk of the documentation can be found * in .nmod_mat_poly.h . * */ //@{ // TODO DOC // appbas must be initialized with right dimensions // shift=NULL for uniform shift FLINT_DLL void nmod_poly_mat_mbasis(nmod_poly_mat_t appbas, slong * shift, const nmod_poly_mat_t pmat, ulong order); //@} // doxygen group: M-Basis algorithm (uniform approximant order) /** @name PM-Basis algorithm (uniform approximant order) * \anchor pmbasis * * These functions compute a `shift`-minimal ordered weak Popov approximant * basis for `(pmat,orders)` in the case where `orders` is given by a single * integer `orders = (order,...order)`. They use a divide and conquer approach, * computing a first basis at order `order/2`, finding the so-called _residual * matrix_, computing a second basis at order `order/2`, and deducing the * sought basis by multiplying the two obtained bases. * * The first recursive call returns an approximant basis `appbas1` such that * `appbas1*pmat = 0 mod x^{order/2}`, and the residual matrix has the same * dimensions as `pmat` and is defined by the matrix middle product * `(x^{-order/2} appbas1*pmat) mod x^{order/2}`. * * At the end of the computation, the vector `shift` contains the shifted row * degree of `appbas`, for the input shift. * * This is inspired from the algorithm _pmbasis_ described in * - P. Giorgi, C.-P. Jeannerod, G. Villard. Proceeding ISSAC 2003, * - P. Giorgi, R. Lebreton. Proceedings ISSAC 2014. */ //@{ // TODO DOC // appbas must be initialized with right dimensions // shift=NULL for uniform shift FLINT_DLL void nmod_poly_mat_pmbasis(nmod_poly_mat_t appbas, slong * shift, const nmod_poly_mat_t pmat, slong order); //@} // doxygen group: PM-Basis algorithm (uniform approximant order) #ifdef __cplusplus } #endif #endif // NMOD_POLY_MAT_APPROXIMANT_H /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s msolve-0.6.5/src/upolmat/nmod_poly_mat_utils.c000066400000000000000000000077011456710632100215360ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Vincent Neiger * Mohab Safey El Din */ #include #include "nmod_mat_poly.h" #include "nmod_poly_mat_utils.h" void nmod_poly_mat_shift_right(nmod_poly_mat_t smat, const nmod_poly_mat_t pmat, slong k) { for (slong i = 0; i < smat->r; i++) for (slong j = 0; j < smat->c; j++) nmod_poly_shift_right(smat->rows[i] + j, pmat->rows[i] + j, k); } // computes x**(-d) (A*B mod x**h) void nmod_poly_mat_middle_product(nmod_poly_mat_t res, const nmod_poly_mat_t A, const nmod_poly_mat_t B, slong d, slong h) { nmod_poly_mat_mul(res, A, B); nmod_poly_mat_truncate(res, h); nmod_poly_mat_shift_right(res, res, d); } void nmod_poly_mat_set_trunc_from_mat_poly(nmod_poly_mat_t pmat, const nmod_mat_poly_t matp, slong order) { if (order > matp->length) order = matp->length; // prepare memory for (slong i = 0; i < pmat->r; i++) for (slong j = 0; j < pmat->c; j++) nmod_poly_fit_length(nmod_poly_mat_entry(pmat, i, j), order); // fill data for (slong k = 0; k < order; k++) for (slong i = 0; i < pmat->r; i++) for (slong j = 0; j < pmat->c; j++) nmod_poly_mat_entry(pmat, i, j)->coeffs[k] = nmod_mat_poly_entry(matp, k, i, j); // normalize for (slong i = 0; i < pmat->r; i++) for (slong j = 0; j < pmat->c; j++) { _nmod_poly_set_length(nmod_poly_mat_entry(pmat, i, j), order); _nmod_poly_normalise(nmod_poly_mat_entry(pmat, i, j)); } } void nmod_poly_mat_degree_matrix(fmpz_mat_t dmat, const nmod_poly_mat_t mat) { for(slong i = 0; i < mat->r; i++) for(slong j = 0; j < mat->c; j++) *fmpz_mat_entry(dmat, i, j) = nmod_poly_degree(nmod_poly_mat_entry(mat, i, j)); } #if __FLINT_VERSION < 3 void nmod_poly_mat_truncate(nmod_poly_mat_t pmat, long len) { for (slong i = 0; i < pmat->r; i++) for (slong j = 0; j < pmat->c; j++) nmod_poly_truncate(pmat->rows[i] + j, len); } #endif #if __FLINT_VERSION < 3 void nmod_poly_mat_print(const nmod_poly_mat_t mat, const char * var) { slong rdim = mat->r, cdim = mat->c; flint_printf("<%wd x %wd matrix over Z/nZ[%s]>\n", mat->r, mat->c, var); flint_printf("["); for (slong i = 0; i < rdim; i++) { flint_printf("["); for (slong j = 0; j < cdim; j++) { nmod_poly_print_pretty(nmod_poly_mat_entry(mat, i, j), var); if (j+1 < cdim) flint_printf(", "); } if (i != rdim -1) flint_printf("],\n"); else flint_printf("]"); } flint_printf("]\n"); } #endif void nmod_poly_mat_degree_matrix_print_pretty(const nmod_poly_mat_t mat) { fmpz_mat_t dmat; fmpz_mat_init(dmat, mat->r, mat->c); nmod_poly_mat_degree_matrix(dmat, mat); fmpz_mat_print_pretty(dmat); printf("\n"); fmpz_mat_clear(dmat); } /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s msolve-0.6.5/src/upolmat/nmod_poly_mat_utils.h000066400000000000000000000132131456710632100215360ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Vincent Neiger * Mohab Safey El Din */ #ifndef NMOD_POLY_MAT_UTILS_H #define NMOD_POLY_MAT_UTILS_H /** \brief Basic routines for univariate polynomial matrices over `nmod` * \file nmod_poly_mat_utils.h * \date 2023-09-08 * * This provides additional functions for FLINT's for matrices over the * univariate polynomials, with type `nmod_poly_mat` (coefficients in a finite * field Z/pZ for "small" p). * */ // FLINT includes #include #include #include // for nmod_mat_poly_t #include "nmod_mat_poly.h" #ifdef __cplusplus extern "C" { #endif // TODO remove once using flint's comp instead /** apply permutation to vector */ NMOD_POLY_MAT_INLINE void apply_perm_to_vector(slong *res, const slong *initial_vect, const slong *perm, slong length) { for (slong i = 0; i < length; i++) res[perm[i]] = initial_vect[i]; } /** computes x**(-d) (A*B mod x**h) */ void nmod_poly_mat_middle_product(nmod_poly_mat_t res, const nmod_poly_mat_t A, const nmod_poly_mat_t B, slong d, slong h); #if __FLINT_VERSION < 3 /** Truncate `pmat` at order `len` */ void nmod_poly_mat_truncate(nmod_poly_mat_t pmat, long len); #endif /** @name Shifts (multiplication by powers of the variable) * * Left and right shift operations (X is the variable): * - LeftShift by n means multiplication by X^n * - RightShift by n means division by X^n * - shift `n` has to be nonnegative in both cases. * * In all the following functions which involve an OUT parameter (`svec` or * `smat`), this parameter may alias the corresponding IN parameter (`pvec` or * `pmat`). */ //@{ /** Computes the right `k`-shift `smat` of the polynomial matrix `pmat` */ void nmod_poly_mat_shift_right(nmod_poly_mat_t smat, const nmod_poly_mat_t pmat, slong k); //@} // doxygen group: Shifts (multiplication by powers of the variable) /*------------------------------------------------------------*/ /*------------------------------------------------------------*/ /* SET FROM CONSTANT OR MATP */ /*------------------------------------------------------------*/ /*------------------------------------------------------------*/ /** @name Set from constant matrix and matrix polynomial. * * Provides `set` and `init_set`, from either a constant matrix, * or from a `nmod_mat_poly_t`. * * Two main representations are used for polynomial matrices: * - a polynomial matrix stored as a matrix with polynomial entries, that * is, of type `nmod_poly_mat_t` * - a polynomial matrix stored as a polynomial with matrix coefficients, * that is, of type `nmod_mat_poly_t` * * In the latter representation, the array of matrices has length * `degree(mat)+1`; in particular, the zero matrix may be represented by an * array of length 0. Note also the following requirement: in the second * representation, all the matrix coefficients have the same row and column * dimensions; this is currently assumed to hold, and is not checked by the * algorithms. * * The following functions perform conversions between these types, with two * variants: either the degree is deduced from the input, or a user-provided * truncation order is used. * */ //@{ /** Set from polynomial with matrix coefficients `matp`, truncated at the * specified `order` (a nonnegative integer). */ // TODO benchmark and try variants if needed FLINT_DLL void nmod_poly_mat_set_trunc_from_mat_poly(nmod_poly_mat_t pmat, const nmod_mat_poly_t matp, slong order); /** Set from polynomial with matrix coefficients `matp`. */ // TODO benchmark and try variants if needed NMOD_POLY_MAT_INLINE void nmod_poly_mat_set_from_mat_poly(nmod_poly_mat_t pmat, const nmod_mat_poly_t matp) { nmod_poly_mat_set_trunc_from_mat_poly(pmat, matp, matp->length); } //@} // doxygen group: Conversion from constant matrix and matrix polynomial /*------------------------------------------------------------*/ /*------------------------------------------------------------*/ /* INPUT/OUTPUT */ /*------------------------------------------------------------*/ /*------------------------------------------------------------*/ #if __FLINT_VERSION < 3 /** Matrix pretty print to standard output */ void nmod_poly_mat_print(const nmod_poly_mat_t mat, const char * var); #endif /** Print the degree matrix, see @ref DegreeMatrix */ void nmod_poly_mat_degree_matrix_print_pretty(const nmod_poly_mat_t mat); #ifdef __cplusplus } #endif #endif // NMOD_POLY_MAT_UTILS_H /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s msolve-0.6.5/src/usolve/000077500000000000000000000000001456710632100151405ustar00rootroot00000000000000msolve-0.6.5/src/usolve/Makefile.am000066400000000000000000000012411456710632100171720ustar00rootroot00000000000000noinst_LTLIBRARIES = libusolve.la libusolve_la_SOURCES = usolve.c libusolve_ladir = $(includedir)/msolve/usolve libusolve_la_HEADERS = libusolve.h libusolve_la_CFLAGS = $(SIMD_FLAGS) $(CPUEXT_FLAGS) $(OPENMP_CFLAGS) EXTRA_DIST = libusolve.h \ bisection.h \ debug.h \ descartes.h \ evaluate.h \ libusolve.h \ print_usolve.h \ refine.h \ taylor_shift.h \ univmultiply.h \ data_usolve.c \ debug.c \ descartes.c \ evaluate.c \ print_usolve.c \ refine.c \ taylor_shift.c \ tests.c \ univmultiply.c \ utils.c msolve-0.6.5/src/usolve/bisection.h000066400000000000000000000021631456710632100172720ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include"descartes.h" interval *Bisection_Uspensky(mpz_t *, unsigned long, unsigned long int *, unsigned long int *, usolve_flags *); interval *Bisection_Uspensky_from_root(mpz_t *, unsigned long, unsigned long int *, unsigned long int *, usolve_flags *); msolve-0.6.5/src/usolve/data_usolve.c000066400000000000000000000035571456710632100176240ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ typedef struct{ int search;/*when >0 (resp. <0, =0) computes positive (resp. negative, all) roots */ long int bound_pos; /*log2(M) where M dominates the largest positive root*/ long int bound_neg; /*log2(-M) where M is less than the least negative root*/ int sign;/* when >=0 (resp. <0), one computes non-negative (resp. negative) roots */ int revert; /* when set to 1 one reads input coeffs by ascending degree */ int prec_isole; /* nbr of bits for real root isolation */ int hasrealroots; /*when set to 1, computation stops when one finds a root*/ long int precision_loss; unsigned long int transl; unsigned long int node_looked; unsigned long int half_done; unsigned long int cur_deg; unsigned long int pwx; unsigned long int nblocks; unsigned long int npwr; mpz_t **shift_pwx; mpz_t *tmpol; mpz_t *tmpol_desc; /* used for parallel taylor_shift */ mpz_t **tmp_threads; mpz_t **pols_threads; mpz_t *Values; float time_desc; float time_shift; unsigned int nthreads; unsigned int verbose; unsigned int bfile; unsigned int classical_algo; unsigned int print_stats; int debug; } usolve_flags; msolve-0.6.5/src/usolve/debug.c000066400000000000000000000046161456710632100164010ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include //#include "utils.h" //#include "evaluate.h" //#include "print_usolve.h" /* returns 1 if up has sign change over the interval encoded by root */ /* return 0 otherwise */ static inline int check_sign_change(mpz_t *upoly, unsigned long int deg, interval *root){ if(root->isexact==1){ mpz_t c; mpz_init_set(c, root->numer); // mpz_out_str(stderr, 10, c); puts(""); int s_down = sgn_mpz_poly_eval_at_point_2exp_naive(upoly, deg, &c, root->k); if(s_down!=0){ fprintf(stderr, "Negative (k): Not implemented yet ; skipped but useless with larger precision\n"); return 0; // exit(1); } return 1; } if(root->k<=0){ fprintf(stderr, "Negative (k): Not implemented yet ; skipped but useless with larger precision\n"); return 1; // exit(1); } mpz_t c; mpz_init_set(c, root->numer); // mpz_out_str(stderr, 10, c); puts(""); int s_down = sgn_mpz_poly_eval_at_point_2exp_naive(upoly, deg, &c, root->k); mpz_add_ui(c, c, 1); // mpz_out_str(stderr, 10, c); puts(""); int s_up = sgn_mpz_poly_eval_at_point_2exp_naive(upoly, deg, &c, root->k); mpz_clear(c); if(s_up*s_down<=0){ return 1; } fprintf(stderr, "\nBUG: no sign change\n"); return 0; } static int check_all_sign_changes(mpz_t *upoly, unsigned long int deg, interval *root, unsigned long int nbroots){ int s = 1; for(unsigned long int i =0; i < nbroots; i++){ if((root+i)->isexact==0){ s = check_sign_change(upoly, deg, root+i); if(s==0){ fprintf(stderr, "Error occurred at root %lu\n", i); USOLVEdisplay_roots(stderr, (root+i), 1); fprintf(stderr, "\n"); exit(1); } } } return 1; } msolve-0.6.5/src/usolve/debug.h000066400000000000000000000015771456710632100164110ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ int check_sign_change(mpz_t *, unsigned long int, interval *); int check_all_sign_changes(mpz_t *, unsigned long int, interval *, unsigned long int); msolve-0.6.5/src/usolve/descartes.c000066400000000000000000000122521456710632100172630ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include #include #ifndef USOLVE #define USOLVE #endif static unsigned long descartes_classical(const mpz_t *, mpz_t *, const unsigned long, long, long *); static long descartes_truncate(mpz_t *, const unsigned long, const unsigned long, long, long *, usolve_flags *); /* one assumes upol[0] != 0 */ /* stopped as soon as more than 3 sgn variations are found */ static long mpz_poly_sgn_variations_coeffs(mpz_t* upol, unsigned long deg){ unsigned long int i; long nb = 0; int s = mpz_sgn(upol[deg]); for(i = deg-1; i > 0; i--){ if( mpz_sgn(upol[i]) * s < 0 ){ nb = nb + 1; s = mpz_sgn(upol[i]); if(nb >= 3){ return nb; } } } if(s*mpz_sgn(upol[0]) < 0){ if(nb==0){ } nb = nb + 1; } return nb; } static unsigned long int descartes(mpz_t *upol1, mpz_t *upol2, const unsigned long deg, long sigh, long *flag, usolve_flags *flags){ unsigned long int i; #pragma omp parallel for num_threads(flags->nthreads) for(i = 0; i <= deg; i++){ mpz_set(upol2[i],upol1[deg-i]); } /* Max bit size of coefficients in upol1 */ const unsigned long nbits = mpz_poly_max_bsize_coeffs(upol1, deg); long nb = descartes_truncate(upol2, deg, nbits, sigh, flag, flags); if(nb >= 0){ return nb; } #pragma omp parallel for num_threads(flags->nthreads) for(i = 0; i <= deg; i++){ mpz_set(upol2[i], upol1[deg-i]); } taylorshift1_dac(upol2, deg, flags->tmpol, flags->shift_pwx, flags->pwx, flags->nthreads); nb = mpz_poly_sgn_variations_coeffs(upol2, deg); return nb; } /* assumes upol1 and upol2 are the same polynomials */ static long descartes_truncate(mpz_t *upol2, const unsigned long deg, const unsigned long nbits, long sigh, long *flag, usolve_flags *flags){ int i; /* /\* Max bit size of coefficients in upol1 *\/ */ /* const unsigned long int nbits = mpz_poly_max_bsize_coeffs(upol1, deg); */ const unsigned long int lc = ilog2_mpz(upol2[deg]); /* One wants to divide all coefficients by 2^trunc */ /* Hence only 2*(deg+1) bits are taken into account */ /* After applying a Taylor shift we'll lose deg+1 bits */ /* Should be sufficient for sign variations of coefficients in most cases*/ unsigned long int trunc = nbits - 2 * (deg + 1); /*Necessary to avoid that lead coef becomes 0 after truncation*/ if(lc<=trunc){ trunc = lc - 1; } /* All coefficients are divided by 2^trunc */ /* Only 2*(deg + 1) coeffs are meaningful */ #pragma omp parallel for num_threads(flags->nthreads) for(i = 0; i <= deg; i++){ mpz_tdiv_q_2exp(upol2[i],upol2[i],trunc); } long check = taylorshift1_dac_wsgnvar(upol2, deg, flags->tmpol, flags->shift_pwx, flags->pwx, flags->nthreads); if(check >= 0){ return check; } return -1; } /* upol -> numer( upol( 1 / (x+1) ) ) */ static unsigned long descartes_classical(const mpz_t *upol, mpz_t *tpol, const unsigned long deg, long hsgn, long *bsgn){ unsigned long nb = 0; long j = deg; long t = mpz_sgn(upol[j]); while (j >= 0 && mpz_sgn(upol[j]) == t){ j--; } /* no sgn change in upol */ if (j < 0){ *bsgn = -1; return nb; } for (long i = 0; i <= deg; i++) { mpz_set(tpol[i], upol[i]); } for (long i = 0; i <= deg - 1; i++){ mpz_add(tpol[i+1], tpol[i+1], tpol[i]); } int s = mpz_sgn(tpol[deg]); *bsgn = s && (s == mpz_sgn(upol[0])) && (s == -hsgn); for (long i = 1; i <= deg - 1; i++){ j = deg - i; t = s; while (t == 0){ t = mpz_sgn(tpol[j]); j--; } while (j >= 0 && mpz_sgn(tpol[j]) == t){ j--; } if (j < 0){ return nb; } for (j = 0; j <= deg - i - 1; j++){ mpz_add(tpol[j+1], tpol[j+1], tpol[j]); } if (s == 0){ s = mpz_sgn(tpol[deg-i]); } else{ if (s == -mpz_sgn(tpol[deg-i])){ if((nb == 1 && !*bsgn) || nb == 2){ return (nb + 1); } nb++; s = -s; } } } if(s == -mpz_sgn(tpol[0])){ nb++; } return nb; } msolve-0.6.5/src/usolve/descartes.h000066400000000000000000000026111456710632100172660ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include"taylor_shift.h" #ifndef USOLVE #define USOLVE #endif long USOLVEDescartes_with_taylor_truncate(mpz_t *, mpz_t *, unsigned long, long, long *, usolve_flags *); unsigned long int USOLVEDescartes_with_taylor_truncated_input(mpz_t *, mpz_t *, mpz_t *, unsigned long, long , mpz_t, long, long *, usolve_flags *); unsigned long USOLVEDescartes_with_taylor(mpz_t *, mpz_t *, unsigned long, long, long *, usolve_flags *); unsigned long USOLVEDescartes_classical(mpz_t *, unsigned long, long, long *); msolve-0.6.5/src/usolve/evaluate.c000066400000000000000000000315501456710632100171160ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ /* val / 2^(deg) is up(1/2) */ static inline void mpz_upoly_eval_onehalf(mpz_t *up, unsigned long int deg, mpz_t *val){ long j; mpz_t y; mpz_set(*val, up[deg]); mpz_init(y); for (j = deg - 1; j >= 0; j--){ mpz_mul_2exp(y, up[j], deg - j); mpz_add(*val, *val, y); } mpz_clear(y); } /* [val_do , val_up ] will be an interval containing all the values of the derivative of upoly at [0,1] */ /* [ f_0 + negative part, f_0 + positive_part] */ static inline void mpz_interveval_deriv_01(mpz_t *upol, unsigned long int deg, mpz_t *vup, mpz_t *vdo){ mpz_t x; mpz_set_ui(*vup, 0); mpz_set_ui(*vdo, 0); mpz_init_set(x, upol[deg]); mpz_mul_ui(x, x, deg); if(mpz_sgn(x)==1){ mpz_add(*vup, *vup, x); } if(mpz_sgn(x)==-1){ mpz_add(*vdo, *vdo, x); } for (unsigned long int j = deg - 1; j >= 2; j--){ mpz_mul_ui(x, upol[j], j); if(mpz_sgn(x)==1){ mpz_add(*vup, *vup, x); } if(mpz_sgn(x)==-1){ mpz_add(*vdo, *vdo, x); } } mpz_add(*vdo, *vdo, upol[1]); mpz_add(*vup, *vup, upol[1]); mpz_clear(x); } static inline void basic_mpz_poly_eval_at_point(mpz_t *up, unsigned long int deg, mpz_t *c, mpz_t *val){ mpz_set_ui(*val,0); for(unsigned int i = deg; i > 0; i--){ mpz_add(*val, *val, up[i]); mpz_mul(*val, *val, *c); } mpz_add(*val, *val, up[0]); } static inline int sgn_mpz_poly_eval_at_point_naive(mpz_t *upoly, unsigned long int deg, mpz_t *c, int classical_algo){ mpz_t val; mpz_init(val); basic_mpz_poly_eval_at_point(upoly, deg, c, &val); int s = mpz_sgn(val); mpz_clear(val); return s; } /* Evaluates upol at c/2^k using a Horner scheme In the end, one has val/2(k*deg)=up(c / 2^k) */ void mpz_poly_eval_2exp_naive(mpz_t *upol, long int deg, mpz_t *c, const long k, mpz_t *val, mpz_t *tmp){ if(deg == -1){ mpz_set_ui(*val, 0); return; } if(deg == 0){ mpz_set(*val, upol[0]); return; } mpz_set(*val, upol[deg]); mpz_mul(*val, *val, *c); for(unsigned long int i = deg - 1; i > 0; i--){ mpz_mul_2exp(*tmp, upol[i], (deg-i)*k); mpz_add(*val, *val, *tmp); mpz_mul(*val, *val, *c); } mpz_mul_2exp(*tmp, upol[0], deg*k); mpz_add(*val, *val, *tmp); } /* Evaluates upol at c/2^k using a Horner scheme In the end, one has val/2(k*deg)=up(c / 2^k) */ void mpz_poly_eval_2exp_naive2(mpz_t *upol, long int deg, mpz_t c, const long k, mpz_t val, mpz_t tmp){ if(deg == -1){ mpz_set_ui(val, 0); return; } if(deg == 0){ mpz_set(val, upol[0]); return; } mpz_set(val, upol[deg]); mpz_mul(val, val, c); for(unsigned long int i = deg - 1; i > 0; i--){ mpz_mul_2exp(tmp, upol[i], (deg-i)*k); mpz_add(val, val, tmp); mpz_mul(val, val, c); } mpz_mul_2exp(tmp, upol[0], deg*k); mpz_add(val, val, tmp); } /* Evaluation over an interval using a Horner scheme */ /* assumes a and b have the same sign */ /* returns (mpz_sgn(val_do) != mpz_sgn(val_up)); */ int mpz_poly_eval_interval(mpz_t *up, const long int deg, const long k, mpz_t a, mpz_t b, mpz_t tmp, mpz_t val_do, mpz_t val_up){ if(deg == -1){ mpz_set_ui(val_up, 0); mpz_set_ui(val_do, 0); return 0; } if(deg == 0){ mpz_set(val_up, up[0]); mpz_set(val_do, up[0]); return 0; } mpz_set(val_up, up[deg]); mpz_set(val_do, up[deg]); mpz_t s; mpz_init(s); if(mpz_sgn(a) != mpz_sgn(b) && mpz_sgn(a) != 0 && mpz_sgn(b) != 0){ fprintf(stderr, "Entries of mpz_poly_eval_interval are incorrect\n"); fprintf(stderr, "a and b should have same sign"); mpz_out_str(stderr, 10, a); mpz_out_str(stderr, 10, b); mpz_clear(s); exit(1); } /* a and b are non-negative */ if(mpz_sgn(a) >= 0){ for(long i = deg - 1; i >= 0; i--){ if(mpz_sgn(val_do) >= 0){ mpz_mul_2exp(tmp, up[i], k*(deg - i)); mpz_mul(val_do, val_do, a); mpz_add(val_do, val_do, tmp); mpz_mul(val_up, val_up, b); mpz_add(val_up, val_up, tmp); } else{ mpz_mul_2exp(tmp, up[i], k*(deg - i)); mpz_mul(val_do, val_do, b); mpz_add(val_do, val_do, tmp); mpz_mul(val_up, val_up, a); mpz_add(val_up, val_up, tmp); } if(mpz_cmp(val_do, val_up) > 0){ fprintf(stderr, "BUG ici (den_do > den_up)\n"); exit(1); } } } else{ /* a and b are negative */ for(long i = deg - 1; i >= 0; i--){ if(mpz_sgn(val_do) >= 0){ mpz_set(s, val_do); mpz_mul_2exp(tmp, up[i], k*(deg - i)); mpz_mul(val_do, val_up, a); mpz_add(val_do, val_do, tmp); mpz_mul(val_up, s, b); mpz_add(val_up, val_up, tmp); } else{ mpz_set(s, val_do); mpz_mul_2exp(tmp, up[i], k*(deg - i)); mpz_mul(val_do, val_up, b); mpz_add(val_do, val_do, tmp); mpz_mul(val_up, s, a); mpz_add(val_up, val_up, tmp); } if(mpz_cmp(val_do, val_up) > 0){ fprintf(stderr, "BUG ici2 (val_do > val_up)\n"); fprintf(stderr, "=> sign of val_do = %d\n", mpz_sgn(val_do)); fprintf(stderr, "=> sign of val_up = %d\n", mpz_sgn(val_up)); exit(1); } } } mpz_clear(s); return (mpz_sgn(val_do) != mpz_sgn(val_up)); } /* evaluates up (of degree deg) over the interval through scalar product up*xdo and up*xup up to precision corr Values are stored in val_do, val_up => [val_do / 2^corr, val_up/2^corr] returns (mpz_sgn(val_do) != mpz_sgn(val_up)) */ int mpz_scalar_product_interval(mpz_t *up, const long int deg, const long k, mpz_t *xdo, mpz_t *xup, mpz_t tmp, mpz_t val_do, mpz_t val_up, long corr){ if(deg == -1){ mpz_set_ui(val_up, 0); mpz_set_ui(val_do, 0); return 0; } if(deg == 0){ mpz_set(val_up, up[0]); mpz_set(val_do, up[0]); mpz_mul_2exp(val_up, val_up, corr); mpz_mul_2exp(val_do, val_do, corr); return 0; } mpz_set_ui(val_up, 0); mpz_set_ui(val_do, 0); for(long i = 0; i <= deg; i++){ if(mpz_sgn(up[i]) >= 0){ mpz_mul(tmp, up[i], xup[i]); mpz_add(val_up, val_up, tmp); mpz_mul(tmp, up[i], xdo[i]); mpz_add(val_do, val_do, tmp); } else{ mpz_mul(tmp, up[i], xdo[i]); mpz_add(val_up, val_up, tmp); mpz_mul(tmp, up[i], xup[i]); mpz_add(val_do, val_do, tmp); } } return (mpz_sgn(val_do) != mpz_sgn(val_up)); } /* [ val_do / 2^prec, val_up / 2^prec ] will contain */ /* up( [ xdo[1], xup[1] ] ) */ /*toto*/ /* [ val_do / 2^prec, val_up / 2^prec ] will contain */ /* up( [ xdo[1], xup[1] ] ) */ /* xup[i] and xdo[i] are given mod 2^corr when i%b == 0 */ int lazy_mpz_poly_eval_interval(mpz_t *up, const unsigned long int deg, const long k, mpz_t *xdo, mpz_t *xup, const long prec, const long corr, const long b, mpz_t tmp, mpz_t val_do, mpz_t val_up){ if(deg==-1){ mpz_set_ui(val_up, 0); mpz_set_ui(val_do, 0); return 0; } if(deg==0){ mpz_set(val_up, up[0]); mpz_set(val_do, up[0]); return 0; } mpz_set_ui(val_up, 0); mpz_set_ui(val_do, 0); const long t = (deg) / b; long rd = (deg) % b; mpz_t fdo, fup; mpz_init(fdo); mpz_init(fup); for(long j = 0; j < t; j++){ mpz_set_ui(fdo, 0); mpz_set_ui(fup, 0); for(long i = 0; i < b; i++){ if(mpz_sgn(up[i+j*b]) >= 0){ mpz_mul(tmp, up[i+j*b], xup[i]); mpz_mul_2exp(tmp, tmp, k*(b - 1 - i)); mpz_add(fup, fup, tmp); mpz_mul(tmp, up[i+j*b], xdo[i]); mpz_mul_2exp(tmp, tmp, k*(b - 1 - i)); mpz_add(fdo, fdo, tmp); } else{ mpz_mul(tmp, up[i+j*b], xdo[i]); mpz_mul_2exp(tmp, tmp, k*(b - 1 - i)); mpz_add(fup, fup, tmp); mpz_mul(tmp, up[i+j*b], xup[i]); mpz_mul_2exp(tmp, tmp, k*(b - 1 - i)); mpz_add(fdo, fdo, tmp); } } if(mpz_cmp(fdo, fup) > 0){ fprintf(stderr, "BUG in preprocess eval (fdo > fup)\n"); mpz_out_str(stderr, 10, fdo); fprintf(stderr, "\n"); mpz_out_str(stderr, 10, fup); fprintf(stderr, "\n"); exit(1); } if(mpz_sgn(fdo) < 0){ mpz_mul(fdo, fdo, xup[j*b]); } else{ mpz_mul(fdo, fdo, xdo[j*b]); } if(mpz_sgn(fup) < 0){ mpz_mul(fup, fup, xdo[j*b]); } else{ mpz_mul(fup, fup, xup[j*b]); } mpz_mul_2exp(fdo, fdo, t+prec); mpz_mul_2exp(fup, fup, t+prec); if(j){ mpz_fdiv_q_2exp(fdo, fdo, k*(b-1) + corr); mpz_cdiv_q_2exp(fup, fup, k*(b-1) + corr); } else{ mpz_fdiv_q_2exp(fdo, fdo, k*(b-1) ); mpz_cdiv_q_2exp(fup, fup, k*(b-1) ); } mpz_add(val_do, val_do, fdo); mpz_add(val_up, val_up, fup); if(mpz_cmp(fdo, fup) > 0){ fprintf(stderr, "BUG in preprocess2 eval (fdo > fup)\n"); mpz_out_str(stderr, 10, xdo[j*b]); fprintf(stderr, "\n"); mpz_out_str(stderr, 10, xup[j*b]); fprintf(stderr, "\n"); fprintf(stderr, "cmp = %d\n", mpz_cmp(xdo[j*b], xup[j*b])); exit(1); } if(mpz_cmp(val_do, val_up) > 0){ fprintf(stderr, "BUG in eval (val_do > val_up)\n"); mpz_out_str(stderr, 10, val_do); fprintf(stderr, "\n"); mpz_out_str(stderr, 10, val_up); fprintf(stderr, "\n"); exit(1); } } if(rd){ mpz_set_ui(fdo, 0); mpz_set_ui(fup, 0); for(long i = 0; i <= rd; i++ ){ if(mpz_sgn(up[i+t*b]) >= 0){ mpz_mul(tmp, up[i+t*b], xup[i]); mpz_mul_2exp(tmp, tmp, k*(rd - i)); mpz_add(fup, fup, tmp); mpz_mul(tmp, up[i+t*b], xdo[i]); mpz_mul_2exp(tmp, tmp, k*(rd - i)); mpz_add(fdo, fdo, tmp); } else{ mpz_mul(tmp, up[i+t*b], xdo[i]); mpz_mul_2exp(tmp, tmp, k*(rd - i)); mpz_add(fup, fup, tmp); mpz_mul(tmp, up[i+t*b], xup[i]); mpz_mul_2exp(tmp, tmp, k*(rd - i)); mpz_add(fdo, fdo, tmp); } } if(mpz_cmp(fdo, fup) > 0){ fprintf(stderr, "BUG in preprocess3 init eval (fdo > fup)\n"); exit(1); } if(mpz_cmp(val_do, val_up) > 0){ fprintf(stderr, "BUG in eval (val_do > val_up)\n"); exit(1); } if(mpz_cmp(fdo, fup) > 0){ fprintf(stderr, "BUG in preprocess3 init0 eval (fdo > fup)\n"); exit(1); } if(mpz_sgn(fdo) < 0){ mpz_mul(fdo, fdo, xup[t*b]); } else{ mpz_mul(fdo, fdo, xdo[t*b]); } if(mpz_sgn(fup) < 0){ mpz_mul(fup, fup, xdo[t*b]); } else{ mpz_mul(fup, fup, xup[t*b]); } mpz_mul_2exp(fdo, fdo, t+prec); mpz_mul_2exp(fup, fup, t+prec); if(t){ mpz_cdiv_q_2exp(fup, fup, k*(rd) + corr); mpz_fdiv_q_2exp(fdo, fdo, k*(rd) + corr); } else{ mpz_cdiv_q_2exp(fup, fup, k*(rd) ); mpz_fdiv_q_2exp(fdo, fdo, k*(rd) ); } mpz_add(val_do, val_do, fdo); mpz_add(val_up, val_up, fup); } mpz_mul_2exp(val_do, val_do, prec); mpz_mul_2exp(val_up, val_up, prec); mpz_fdiv_q_2exp(val_do, val_do, t+prec); mpz_cdiv_q_2exp(val_up, val_up, t+prec); mpz_clear(fdo); mpz_clear(fup); return (mpz_sgn(val_do) != mpz_sgn(val_up)); } static inline int sgn_mpz_poly_eval_at_point_2exp_naive(mpz_t *upol, unsigned long int deg, mpz_t *c, int k){ mpz_t val, coeff; mpz_init(coeff); mpz_init_set(val, upol[deg]); mpz_mul(val, val, *c); for(unsigned long int i=deg-1; i>0; i--){ mpz_mul_2exp(coeff, upol[i], (deg-i)*k); mpz_add(val, val, coeff); mpz_mul(val, val, *c); } mpz_mul_2exp(coeff, upol[0], deg*k); mpz_add(val, val, coeff); int s = mpz_sgn(val); mpz_clear(val); mpz_clear(coeff); return s; } msolve-0.6.5/src/usolve/evaluate.h000066400000000000000000000045221456710632100171220ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ void basic_mpz_poly_eval_at_point(mpz_t *, unsigned long int, mpz_t*, mpz_t *); void mpz_poly_eval_at_point_2exp(mpz_t *, unsigned long int, unsigned long int, unsigned long int, mpz_t, int, int, mpz_t *, mpz_t *, double *); void mpz_poly_eval_at_point_2exp_ui(mpz_t *, unsigned long int, unsigned long int, unsigned long int, unsigned long int, int, int, mpz_t *, mpz_t *, double *); int sgn_mpz_poly_eval_at_point_2exp(mpz_t *, unsigned long int, unsigned long int, unsigned long int, mpz_t *, int, mpz_t *, mpz_t *, int *, double *); int sgn_mpz_poly_eval_at_point_2exp_ui(mpz_t *, unsigned long int, unsigned long int, unsigned long int, unsigned long int, int, mpz_t *, mpz_t *, int *, double *); int sgn_mpz_poly_eval_at_point_naive(mpz_t *, unsigned long int, mpz_t *, int); void mpz_poly_eval_2exp_naive(mpz_t *, long int, mpz_t *, const long int, mpz_t *, mpz_t *); int sgn_mpz_poly_eval_at_point_2exp_naive(mpz_t *, unsigned long int, mpz_t*, int); int sgn_mpz_poly_eval_at_point_2exp_naive2(mpz_t *, unsigned long int, mpz_t, int); msolve-0.6.5/src/usolve/libusolve.h000066400000000000000000000046041456710632100173210ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ interval *real_roots(mpz_t *, unsigned long, unsigned long int *, unsigned long int *, const int32_t, int, int); void display_roots_system(FILE *, interval *, unsigned long int); void display_root(FILE *, interval *); unsigned long int mpz_poly_max_bsize_coeffs(mpz_t *, unsigned long int); unsigned long int mpz_poly_min_bsize_coeffs(mpz_t *, unsigned long int); void mpz_poly_eval_2exp_naive(mpz_t *, long int, mpz_t *, const long int, mpz_t *, mpz_t *); void mpz_poly_eval_2exp_naive2(mpz_t *, unsigned long int, mpz_t, const int, mpz_t, mpz_t); void get_values_at_bounds(mpz_t *, unsigned long int, interval *, mpz_t *); void refine_QIR_positive_root(mpz_t *, long int *, interval *, mpz_t *, int, int); int mpz_scalar_product_interval(mpz_t *, unsigned long int, long, mpz_t *, mpz_t *, mpz_t, mpz_t, mpz_t, long); int mpz_poly_eval_interval(mpz_t *, unsigned long int, long, mpz_t, mpz_t, mpz_t, mpz_t, mpz_t); int lazy_mpz_poly_eval_interval(mpz_t *, unsigned long int, long, mpz_t *, mpz_t *, long, long, long, mpz_t, mpz_t, mpz_t); int lazy_mpz_poly_eval_interval_old(mpz_t *, unsigned long int, long, mpz_t *, mpz_t *, long, long, long, mpz_t, mpz_t, mpz_t); msolve-0.6.5/src/usolve/print_usolve.c000066400000000000000000000053661456710632100200470ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include #include static void display_left(FILE * stream, interval *root){ if (root->k <= 0){ mpz_out_str(stream, 10, root->numer); } else{ mpz_out_str(stream, 10, root->numer); fprintf(stream, "/2^%ld", root->k); } } static void display_right(FILE * stream, interval *root, mpz_t tmp){ if (root->k <= 0){ mpz_set_ui(tmp, 1); mpz_mul_2exp(tmp, tmp, -root->k); mpz_add(tmp, root->numer, tmp); mpz_out_str(stream, 10, tmp); } else{ mpz_add_ui(tmp, root->numer, 1); mpz_out_str(stream, 10, tmp); fprintf(stream, "/2^%ld", root->k); } fprintf(stream, "]"); } static void display_left_in_file(FILE * stream, interval *root){ mpz_out_str(stream, 10, root->numer); fprintf(stream, " "); fprintf(stream, "%ld ", root->k); fprintf(stream, "%d\n", root->isexact); } void display_root(FILE *stream, interval* root){ mpz_t tmp; mpz_init(tmp); fprintf(stream, "["); display_left(stream, root); fprintf(stream, ", "); if (root->isexact == 1) { display_left(stream, root); fprintf(stream, "]"); return; } display_right(stream, root, tmp); mpz_clear(tmp); } void USOLVEdisplay_roots(FILE *stream, interval *roots, unsigned long int nbroots){ fprintf(stream,"["); for(unsigned long int i=0;i * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ //#include "header.h" void USOLVEdisplay_roots(FILE *, interval *, unsigned long int); void USOLVEdisplay_roots_system(interval *, unsigned long int); //void USOLVEdisplay_root(FILE *, interval *); void USOLVEdisplay_roots_in_file(FILE *, interval*, unsigned long int); msolve-0.6.5/src/usolve/refine.c000066400000000000000000000657661456710632100166000ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef USOLVE #define USOLVE #endif /* based on Quadratic interval refinement for real roots */ /* J. Abott, ACM communications in computer algebra */ static void make_exact_root(mpz_t *upol, unsigned long int *deg, interval *rt, mpz_t *x, int k){ mpz_set(rt->numer, *x); rt->k = k; rt->isexact=1; if(k>=0){ USOLVEnumer_quotient(upol, deg, rt->numer, k); } else{ USOLVEnumer_quotient(upol, deg, rt->numer, 0); } } /* computes 2^logN f(a) / (f(a) - f(b)) where f(a) = vala, f(b) = valb */ static long long int index_linearinterp(mpz_t *vala, mpz_t *valb, mpz_t *q, long long int logN){ mpz_sub(*valb, *vala, *valb); mpz_mul_2exp(*vala, *vala, logN); mpz_tdiv_q(*q, *vala, *valb); long int sizeq = ilog2_mpz(*q); if(sizeq >= 8 * sizeof(long long int)){ if(sizeq > logN){ fprintf(stderr,"Valeur de q = "); mpz_out_str(stderr, 10, *q);puts(""); fprintf(stderr, "Valeur de Nlog = %lld\n", logN); fprintf(stderr, "ilog2(q) = %ld\n", sizeq); return -2; } return -1; } long long int index = mpz_get_ui(*q); return index; } static void getx_and_eval_2exp(mpz_t *upol, unsigned long int deg, mpz_t *a, mpz_t *x, mpz_t *value, mpz_t *q, int k, long int index){ mpz_set(*x, *a); mpz_add_ui(*x, *x, index); mpz_poly_eval_2exp_naive(upol, deg, x, k, value, q); } static void getx_and_eval_2exp_mpzidx(mpz_t *upol, unsigned long int deg, mpz_t *a, mpz_t *x, mpz_t *value, mpz_t *q, int k, mpz_t* index_gmp){ mpz_set(*x, *a); mpz_add(*x, *x, *index_gmp); mpz_poly_eval_2exp_naive(upol, deg, x, k, value, q); } static void getx_and_eval_2expleft(mpz_t *upol, unsigned long int deg, mpz_t *a, mpz_t *x, mpz_t *value, mpz_t *q, int k, long int index){ mpz_set(*x, *a); mpz_sub_ui(*x, *x, index); mpz_poly_eval_2exp_naive(upol, deg, x, k, value, q); } /* assumes k >= -2 */ static void getx_and_eval(mpz_t *upol, unsigned long int deg, mpz_t *a, mpz_t *x, mpz_t *value, mpz_t *q, long int Nlog, long int k, long int index){ if(k-Nlog>=0){ mpz_set_ui(*x, 1); mpz_mul_2exp(*x, *x, k - Nlog); mpz_mul_ui(*x,*x,index); mpz_add(*x, *x, *a); mpz_poly_eval_2exp_naive(upol, deg, x, 0, value, q); } else{ mpz_set(*x, *a); mpz_mul_2exp(*x, *x, Nlog - k); mpz_add_ui(*x, *x, index); mpz_poly_eval_2exp_naive(upol, deg, x, Nlog - k, value, q); } } static void getx_and_eval_mpzidx(mpz_t *upol, unsigned long int deg, mpz_t *a, mpz_t *x, mpz_t *value, mpz_t *q, long int Nlog, long int k, mpz_t *index){ if(k-Nlog >= 0){ mpz_set_ui(*x, 1); mpz_mul_2exp(*x, *x, k - Nlog); mpz_mul(*x, *x, *index); mpz_add(*x, *x, *a); mpz_poly_eval_2exp_naive(upol, deg, x, 0, value, q); } else{ mpz_set(*x, *a); mpz_mul_2exp(*x, *x, Nlog - k); mpz_add(*x, *x, *index); mpz_poly_eval_2exp_naive(upol, deg, x, Nlog - k, value, q); } } static int right_interval_2exp(mpz_t *upol, unsigned long int *deg_ptr, interval *rt, mpz_t *x, mpz_t *b, mpz_t *vala, mpz_t *valb, mpz_t *q, int k, int newk){ mpz_swap(*x, *b); mpz_swap(*vala, *valb); getx_and_eval_2exp(upol, *deg_ptr, x, b, valb, q, newk, 1); int sgnb = mpz_sgn(*valb); int sgnx = mpz_sgn(*vala); if(sgnb==0){ make_exact_root(upol, deg_ptr, rt, b, newk); return 1; } if(sgnx!=sgnb){ mpz_set(rt->numer, *x); rt->k = newk; return 1; } return 0; } static int left_interval_2exp(mpz_t *upol, unsigned long int *deg_ptr, interval *rt, mpz_t *x, mpz_t *b, mpz_t *vala, mpz_t *valb, mpz_t *q, int k, int newk){ getx_and_eval_2expleft(upol, *deg_ptr, x, b, valb, q, newk, 1); mpz_swap(*x, *b); mpz_swap(*vala, *valb); int sgnb = mpz_sgn(*valb); int sgnx = mpz_sgn(*vala); if(sgnx==0){ make_exact_root(upol, deg_ptr, rt, x, newk); return 1; } if(sgnx!=sgnb){ mpz_set(rt->numer, *x); rt->k = newk; return 1; } return 0; } static int right_interval(mpz_t *upol, unsigned long int *deg_ptr, interval *rt, mpz_t *x, mpz_t *b, mpz_t *vala, mpz_t *valb, mpz_t *q, int Nlog, int k, int newk){ mpz_swap(*x, *b); mpz_swap(*vala, *valb); if(k-Nlog>=0){ mpz_set_ui(*b, 1); mpz_mul_2exp(*b, *b, k-Nlog); mpz_add(*b, *x, *b); mpz_poly_eval_2exp_naive(upol, *deg_ptr, b, 0, valb, q); } else{ mpz_add_ui(*b, *x, 1); mpz_poly_eval_2exp_naive(upol, *deg_ptr, b, Nlog - k, valb, q); } int sgnb = mpz_sgn(*valb); int sgnx = mpz_sgn(*vala); if(sgnb==0){ make_exact_root(upol, deg_ptr, rt, b, newk); return 1; } if(sgnx!=sgnb){ mpz_set(rt->numer, *x); if(k-Nlog>=0){ rt->k = newk; } else{ rt->k = Nlog - k; } return 1; } return 0; } static int left_interval(mpz_t *upoly, unsigned long int *deg_ptr, interval *rt, mpz_t *x, mpz_t *b, mpz_t *vala, mpz_t *valb, mpz_t *q, int Nlog, int k, int newk){ if(k-Nlog>=0){ mpz_set_ui(*b, 1); mpz_mul_2exp(*b, *b, k-Nlog); mpz_sub(*b, *x, *b); mpz_poly_eval_2exp_naive(upoly, *deg_ptr, b, 0, valb, q); } else{ mpz_sub_ui(*b, *x, 1); mpz_poly_eval_2exp_naive(upoly, *deg_ptr, b, Nlog - k, valb, q); } mpz_swap(*x, *b); mpz_swap(*vala, *valb); int sgnb = mpz_sgn(*valb); int sgnx = mpz_sgn(*vala); if(sgnx==0){ make_exact_root(upoly, deg_ptr, rt, x, newk); return 1; } if(sgnx!=sgnb){ mpz_set(rt->numer, *x); if(k-Nlog>=0){ rt->k = newk; } else{ rt->k = Nlog - k; } return 1; } return 0; } static void refine_root_by_N_positive_k(mpz_t *upol, unsigned long int *deg_ptr, interval *rt, mpz_t *tab, long long int Nlog, int *success, int verbose){ long k = (rt-> k); long newk = k+Nlog; int sgna, sgnb, sgnx; long long int index; mpz_t *vala = (tab); mpz_t *valb = (tab+1); mpz_t *b = (tab+2); mpz_t *q = (tab+3); mpz_t *x = (tab+4); mpz_t *tmpvala = (tab+5); mpz_t *tmpvalb = (tab+6); mpz_t *index_gmp = (tab+7); mpz_set(*tmpvala, *vala); mpz_set(*tmpvalb, *valb); *success = 1; sgna = mpz_sgn(*vala); sgnb = mpz_sgn(*valb); /* computes 2^logN f(a) / (f(a) - f(b)) where f(a) = vala, f(b) = valb */ index = index_linearinterp(vala, valb, index_gmp, Nlog); mpz_set(*vala, *tmpvala); mpz_set(*valb, *tmpvalb); unsigned long long maxindex = (1<<(Nlog)); if(index == -2 || index == 0 || (LOG2(index) > Nlog && index > 0) ){ if(Nlog == 2) index = 2; else{ *success = 0; mpz_set(*vala, *tmpvala); mpz_set(*valb, *tmpvalb); return; } } /* One takes x = (2^Nlog * a + index) / 2^(k+Nlog) */ /* We will compute f(x) and store the value in vala */ mpz_mul_2exp(rt->numer, rt->numer, Nlog); if(index >= 0){ getx_and_eval_2exp(upol, *deg_ptr, &(rt->numer),x, vala, q, newk, index); } else{ getx_and_eval_2exp_mpzidx(upol, *deg_ptr, &(rt->numer), x, vala, q, newk, index_gmp); } sgnx = mpz_sgn(*vala); if(sgnx==0){ make_exact_root(upol, deg_ptr, rt, x, newk); return; } if(sgna == sgnx){ if(index == 3 && Nlog == 2){ mpz_set(rt->numer, *x); rt->k = newk; return; } getx_and_eval_2exp(upol, *deg_ptr, x, b, valb, q, newk, 1); sgnb = mpz_sgn(*valb); if(sgnb==0){ make_exact_root(upol, deg_ptr, rt, b, newk); return; } if(sgnx != sgnb){ mpz_set(rt->numer, *x); rt->k = newk; return; } else{ *success = 0; if(Nlog!=2){ mpz_set(*vala, *tmpvala); mpz_set(*valb, *tmpvalb); mpz_tdiv_q_2exp(rt->numer, rt->numer, Nlog); return; } while(right_interval_2exp(upol, deg_ptr, rt, x, b, vala, valb, q, k, newk)==0 && index <= maxindex){ if(verbose>0){ fprintf(stderr, "->"); } index++; } } } if(sgna != sgnx){ if(index == 1){ rt->k = newk; mpz_swap(*vala, *valb); mpz_set(*vala, *tmpvala); return; } /* One computes x - 2^(k-2) */ getx_and_eval_2expleft(upol, *deg_ptr, x, b, valb, q, newk, 1); /* x is now the least element */ mpz_swap(*x, *b); mpz_swap(*vala, *valb); sgnb = mpz_sgn(*valb); sgnx = mpz_sgn(*vala); if(sgnx==0){ make_exact_root(upol, deg_ptr, rt, x, newk); return; } if(sgnx != sgnb){ mpz_set(rt->numer, *x); rt->k = newk; return; } else{ *success = 0; if(Nlog != 2){ mpz_set(*vala, *tmpvala); mpz_set(*valb, *tmpvalb); mpz_tdiv_q_2exp(rt->numer, rt->numer, Nlog); return; } while(left_interval_2exp(upol, deg_ptr, rt, x, b, vala, valb, q, k, newk) == 0){ if(verbose>0){ fprintf(stderr, "<-"); } } } } } //Dans ce cas, l'intervalle est code de la maniere suivante : //On note u = root->numer et k = root-> k //On considere alors l'intervalle (a, b) avec //a = u et b = u+2^(-k) et k < 0 (donc 2^(-k) est un entier) //tab est un tableau de 7 entiers GMP //tab[0] et tab[1] contiennent f(a) et f(b) respectivement //tab[2] contient b static void refine_root_by_N_negative_k(mpz_t *upol, unsigned long int *deg_ptr, interval *rt, mpz_t *tab, long long int Nlog, int *success, int verbose){ long newk; /* one takes the opposite */ long k = - (rt-> k); int sgna, sgnb, sgnx; long long int index; mpz_t *vala = (tab); mpz_t *valb = (tab+1); mpz_t *b = (tab+2); mpz_t *q = (tab+3); mpz_t *x = (tab+4); mpz_t *tmpvala = (tab+5); mpz_t *tmpvalb = (tab+6); mpz_t *index_gmp = (tab+7); mpz_set(*tmpvala, *vala); mpz_set(*tmpvalb, *valb); *success = 1; sgna = mpz_sgn(*vala); sgnb = mpz_sgn(*valb); index = index_linearinterp(vala, valb, index_gmp, Nlog); mpz_set(*vala, *tmpvala); mpz_set(*valb, *tmpvalb); newk = -k + Nlog; if(index==-2 || index ==0 || (index>0 && LOG2(index) > Nlog)){ if(Nlog == 2)index = 2; else{ *success = 0; mpz_set(*vala, *tmpvala); mpz_set(*valb, *tmpvalb); return; } } if(index >= 0){ getx_and_eval(upol, *deg_ptr, &(rt->numer), x, vala, q, Nlog, k, index); } else{ getx_and_eval_mpzidx(upol, *deg_ptr, &(rt->numer),x, vala, q, Nlog, k, index_gmp); } sgnx = mpz_sgn(*vala); if(sgnx==0){ make_exact_root(upol, deg_ptr, rt, x, newk); return; } if(sgna == sgnx){ if(index == 3 && Nlog == 2){ mpz_set(rt->numer, *x); rt->k = newk; return; } if(k-Nlog>=0){ mpz_set_ui(*b, 1); mpz_mul_2exp(*b, *b, k-Nlog); mpz_add(*b, *x, *b); mpz_poly_eval_2exp_naive(upol, *deg_ptr, b, 0, valb, q); } else{ mpz_add_ui(*b, *x, 1); mpz_poly_eval_2exp_naive(upol, *deg_ptr, b, Nlog - k, valb, q); } sgnb = mpz_sgn(*valb); sgnx = mpz_sgn(*tmpvala); if(sgnb==0){ make_exact_root(upol, deg_ptr, rt, b, newk); return; } if(sgnx != sgnb){ mpz_set(rt->numer, *x); if(k-Nlog>=0){ rt->k = newk; } else{ rt->k = Nlog - k; } return; } else{ *success = 0; if(Nlog!=2){ mpz_set(*vala, *tmpvala); mpz_set(*valb, *tmpvalb); return; } while(right_interval(upol, deg_ptr, rt, x, b, vala, valb, q, Nlog, k, newk) == 0){ if(verbose>0){ fprintf(stderr, "|->"); } } } } if(sgna != sgnx){ if(index == 1){ if(newk > 0){ mpz_mul_2exp(rt->numer, rt->numer, newk); } rt->k = newk; mpz_swap(*vala, *valb); mpz_set(*vala, *tmpvala); return; } if(k-Nlog >= 0){ mpz_set_ui(*b, 1); mpz_mul_2exp(*b, *b, k-Nlog); mpz_sub(*b, *x, *b); mpz_poly_eval_2exp_naive(upol, *deg_ptr, b, 0, valb, q); } else{ mpz_sub_ui(*b, *x, 1); mpz_poly_eval_2exp_naive(upol, *deg_ptr, b, Nlog - k, valb, q); } mpz_swap(*x, *b); mpz_swap(*vala, *valb); sgnb = mpz_sgn(*valb); sgnx = mpz_sgn(*vala); if(sgnx==0){ make_exact_root(upol, deg_ptr, rt, x, newk); return; } if(sgnx != sgnb){ mpz_set(rt->numer, *x); if(k-Nlog>=0){ rt->k = newk; } else{ rt->k = Nlog - k; } return; } else{ *success = 0; if(Nlog!=2){ mpz_set(*vala, *tmpvala); mpz_set(*valb, *tmpvalb); return; } while(left_interval(upol, deg_ptr, rt, x, b, vala, valb, q, Nlog, k, newk) == 0){ if(verbose>0){ fprintf(stderr, "<-|"); } } } } } /* Let f = upol and (a, b) be an isolating interval Computes ( 4 f(a) / (f(a) - f(b)) ) and the closest integer k One has w = (b-a) / 4 and a_i = a_i + i x w Set x = a_k. if f(x) = 0, root is x if sgn(f(x))=sgn(f(a)) : if f(a_{k+1}) =0 root is a_{k+1} if f(x) x f(a_{k+1}) < 0, one gets (x, a_{k+1}) else success = false if sgn(f(x)) = -sgn(f(a)) if f(a_{k-1}) =0 root is a_{k-1} if f(a_{k-1}) x f(x) <0 one gets (a_{k-1}, x) else success = false */ static void refine_positive_root_by_N(mpz_t *upol, unsigned long int *deg_ptr, interval *rt, mpz_t *tab, unsigned long long int Nlog, int *success, int verbose){ *success = 1; long k = rt-> k; if(rt->isexact == 1){ return; } if(k < 0){ /* interval is (rt->numer, rt->numer + 2^(-k)) */ refine_root_by_N_negative_k(upol, deg_ptr, rt, tab, Nlog, success, verbose); } else{ /* interval is (rt->numer/2^k, rt->numer/2^k) */ refine_root_by_N_positive_k(upol, deg_ptr, rt, tab, Nlog, success, verbose); } } void refine_QIR_positive_root(mpz_t *upol, unsigned long int *deg_ptr, interval *rt, mpz_t *tab, int prec, int verbose){ if(rt->isexact==1) return; long long int Nlog = 2; int success = 1; while(rt->isexact != 1 && rt->k < prec){ refine_positive_root_by_N(upol, deg_ptr, rt, tab, Nlog, &success, verbose); if(rt->isexact==1) return; if(mpz_sgn(tab[0]) == mpz_sgn(tab[1])) { fprintf(stderr, "BUG in refine_QIR_positive_root"); exit(1); } if(success == 1){ if(prec - rt->k > Nlog) Nlog=2*Nlog; } else{ if(Nlog>2){ Nlog = Nlog / 2; } } } } void get_values_at_bounds(mpz_t *upol, unsigned long int deg, interval *rt, mpz_t *tab){ if(rt->k > 0){ mpz_poly_eval_2exp_naive(upol, deg, &rt->numer, rt->k, tab, tab+5); mpz_set(tab[3], rt->numer); mpz_add_ui(tab[3], tab[3], 1); mpz_poly_eval_2exp_naive(upol, deg, tab+3, rt->k, tab+1, tab+5); } else{ basic_mpz_poly_eval_at_point(upol, deg, &(rt->numer), tab); mpz_set_ui(tab[3],1); mpz_mul_2exp(tab[3], tab[3], - (rt->k)); mpz_add(tab[3], tab[3], rt->numer); basic_mpz_poly_eval_at_point(upol, deg, tab+3, tab+1); } } static void refine_root_naive(mpz_t *upol, unsigned long int deg, interval *rt, mpz_t *middle, int calgo){ if(rt->isexact == 1){ return; } long newk; int sgn_middle; if((rt->k) >= 0){ /* interval is (numer, numer + 2^(-k)) */ mpz_mul_ui(*middle, rt->numer, 2); mpz_add_ui(*middle, *middle, 1); newk = rt->k + 1; sgn_middle = sgn_mpz_poly_eval_at_point_2exp_naive(upol, deg, middle, newk); } else{ mpz_set_ui(*middle, 1); mpz_mul_2exp(*middle, *middle, - ( (rt->k) + 1)); mpz_add(*middle, *middle, rt->numer); newk = ( (rt->k) + 1 ); sgn_middle = sgn_mpz_poly_eval_at_point_naive(upol, deg, middle, calgo); } int sign_left = rt->sign_left; if(sgn_middle * sign_left<0){ if(newk>0){ mpz_mul_ui(rt->numer, rt->numer, 2); } rt->k = newk; } else{ mpz_set(rt->numer, *middle); rt->k = newk; } } static void remove_exact_roots_by_division(mpz_t *upol, unsigned long int *deg, interval *roots, unsigned long int nbroots, int nthreads){ for(unsigned long int i = 0; i < nbroots; i++){ interval *rt = roots + i; if(rt->isexact==1){ if(rt->k < 0){ USOLVEnumer_quotient(upol, deg, rt->numer, 0); } else{ USOLVEnumer_quotient(upol, deg, rt->numer, rt->k); } } } } /* Refinement using Newton-Interval like technique (but replacing Newton with */ /* linear interpolation) */ /* it takes as input a pointer to deg because it may change after performing */ /* divisions when there are exact roots */ void refine_QIR_roots(mpz_t *upol, unsigned long int *deg, interval *roots, int nbneg, int nbpos, int prec, int verbose, double step, int nthreads){ unsigned long int i; /* table for intermediate values */ mpz_t *tab = (mpz_t *)(malloc(sizeof(mpz_t) * 8)); for(i=0;i<8;i++){ mpz_init(tab[i]); } double e_time = 0, refine_time = realtime(); int nb = nbneg + nbpos; remove_exact_roots_by_division(upol, deg, roots, nb, nthreads); interval *pos_rt = (interval *)(malloc(sizeof(interval))); mpz_init(pos_rt->numer); mpz_t newc; mpz_init(newc); for(i = 0; i <= *deg; i++){ if(i%2 == 1){ mpz_neg(upol[i], upol[i]); } } for(i = 0; i < nbneg; i++){ interval *rt = roots + i; /* display_root(stderr, rt); */ if(rt->k > 0){ if(rt->isexact!=1){ mpz_add_ui(pos_rt->numer, rt->numer, 1); mpz_neg(pos_rt->numer, pos_rt->numer); } pos_rt->k = rt->k; pos_rt->sign_left = - (rt->sign_left); pos_rt->isexact = rt->isexact; } else { if(rt->isexact!=1){ mpz_set_ui(newc, 1); mpz_mul_2exp(newc, newc, -rt->k); mpz_add(pos_rt->numer, rt->numer, newc); mpz_neg(pos_rt->numer, pos_rt->numer); } pos_rt->k = rt->k; pos_rt->sign_left = - (rt->sign_left); pos_rt->isexact = rt->isexact; } if(pos_rt->isexact==0){ get_values_at_bounds(upol, *deg, pos_rt, tab); if(mpz_sgn(tab[0])==0 || mpz_sgn(tab[1])==0){ fprintf(stderr, "Error in refinement (neg. roots): these values should not be zero\n"); exit(1); } refine_QIR_positive_root(upol, deg, pos_rt, tab, prec, verbose); if(mpz_sgn(tab[0])==mpz_sgn(tab[1])){ fprintf(stderr, "BUG in refinement (sgn tab[0]==sgn tab[1]) for neg. roots"); exit(1); } } if(pos_rt->isexact==1){ if(pos_rt->k < 0){ pos_rt->k = 0; } } //We assume precision >=0 if(pos_rt->isexact!=1){ rt->k = pos_rt->k; rt->isexact = pos_rt->isexact; mpz_add_ui(rt->numer, pos_rt->numer, 1); mpz_neg(rt->numer, rt->numer); } else{ rt->k = pos_rt->k; if(rt->isexact!=1){ rt->isexact = pos_rt->isexact; mpz_set(rt->numer, pos_rt->numer); mpz_neg(rt->numer, rt->numer); } } e_time += realtime() - refine_time; if(e_time>=step){ refine_time = realtime(); e_time = 0; if(verbose>=1){ fprintf(stderr, "{%.2f%s}", ((double)i / nb) * 100, "%"); } } } mpz_clear(newc); mpz_clear(pos_rt->numer); free(pos_rt); /* now we refine positive roots */ for(i = 0; i <= *deg; i++){ if(i%2 == 1){ mpz_neg(upol[i], upol[i]); } } for(i=nbneg; i < nb; i++){ interval *rt = roots + i; if(rt->isexact==0){ get_values_at_bounds(upol, *deg, rt, tab); if(mpz_sgn(tab[1])==0 || mpz_sgn(tab[0])==0){ fprintf(stderr, "Error in refinement (pos. roots): these values should not be zero\n"); exit(1); } refine_QIR_positive_root(upol, deg, rt, tab, prec, verbose); if(mpz_sgn(tab[0])==mpz_sgn(tab[1])){ fprintf(stderr,"BUG in refinement (sgn tab[0]=sgn tab[1] for pos. roots)"); exit(1); } if(rt->isexact==1){ if(rt->k < 0){ rt->k = 0; } } } e_time += realtime() - refine_time; if(e_time>=step){ refine_time = realtime(); e_time = 0; if(verbose>=1){ fprintf(stderr, "{%.2f%s}", ((double)(i) / nb) * 100, "%"); } } } if(verbose>=1){ fprintf(stderr, "\n"); } for(i = 0; i < 8; i++){ mpz_clear(tab[i]); } free(tab); } /* Refinement using Newton-Interval like technique (but replacing Newton with */ /* linear interpolation) */ /* it takes as input a pointer to deg because it may change after performing */ /* divisions when there are exact roots */ /* the precision of the refinement depends on the value of the root to be defined */ void refine_QIR_roots_adaptative(mpz_t *upol, unsigned long int *deg, interval *roots, int nbneg, int nbpos, int prec, int verbose, double step, int nthreads){ unsigned long int i; /* table for intermediate values */ mpz_t *tab = (mpz_t *)(malloc(sizeof(mpz_t) * 8)); for(i=0;i<8;i++){ mpz_init(tab[i]); } double e_time = 0, refine_time = realtime(); int nb = nbneg + nbpos; remove_exact_roots_by_division(upol, deg, roots, nb, nthreads); interval *pos_rt = (interval *)(malloc(sizeof(interval))); mpz_init(pos_rt->numer); mpz_t newc; mpz_init(newc); for(i = 0; i <= *deg; i++){ if(i%2 == 1){ mpz_neg(upol[i], upol[i]); } } for(i = 0; i < nbneg; i++){ interval *rt = roots + i; /* display_root(stderr, rt); */ if(rt->k > 0){ if(rt->isexact!=1){ mpz_add_ui(pos_rt->numer, rt->numer, 1); mpz_neg(pos_rt->numer, pos_rt->numer); } pos_rt->k = rt->k; pos_rt->sign_left = - (rt->sign_left); pos_rt->isexact = rt->isexact; } else { if(rt->isexact!=1){ mpz_set_ui(newc, 1); mpz_mul_2exp(newc, newc, -rt->k); mpz_add(pos_rt->numer, rt->numer, newc); mpz_neg(pos_rt->numer, pos_rt->numer); } pos_rt->k = rt->k; pos_rt->sign_left = - (rt->sign_left); pos_rt->isexact = rt->isexact; } if(pos_rt->isexact==0){ get_values_at_bounds(upol, *deg, pos_rt, tab); if(mpz_sgn(tab[0])==0 || mpz_sgn(tab[1])==0){ fprintf(stderr, "Error in refinement (neg. roots): these values should not be zero\n"); exit(1); } long d = 1 + ilog2_mpz(pos_rt->numer) - rt->k; /* fprintf(stderr, "[%d, %ld]", prec, */ /* prec + ((*deg) * MAX(0, d)) / 32); */ refine_QIR_positive_root(upol, deg, pos_rt, tab, prec + (((*deg)-1) * MAX(0, d)) / 32, verbose); if(mpz_sgn(tab[0])==mpz_sgn(tab[1])){ fprintf(stderr, "BUG in refinement (sgn tab[0]==sgn tab[1]) for neg. roots"); exit(1); } } if(pos_rt->isexact==1){ if(pos_rt->k < 0){ pos_rt->k = 0; } } //We assume precision >=0 if(pos_rt->isexact!=1){ rt->k = pos_rt->k; rt->isexact = pos_rt->isexact; mpz_add_ui(rt->numer, pos_rt->numer, 1); mpz_neg(rt->numer, rt->numer); } else{ rt->k = pos_rt->k; if(rt->isexact!=1){ rt->isexact = pos_rt->isexact; mpz_set(rt->numer, pos_rt->numer); mpz_neg(rt->numer, rt->numer); } } e_time += realtime() - refine_time; if(e_time>=step){ refine_time = realtime(); e_time = 0; if(verbose>=1){ fprintf(stderr, "{%.2f%s}", ((double)i / nb) * 100, "%"); } } } mpz_clear(newc); mpz_clear(pos_rt->numer); free(pos_rt); /* now we refine positive roots */ for(i = 0; i <= *deg; i++){ if(i%2 == 1){ mpz_neg(upol[i], upol[i]); } } for(i=nbneg; i < nb; i++){ interval *rt = roots + i; if(rt->isexact==0){ get_values_at_bounds(upol, *deg, rt, tab); if(mpz_sgn(tab[1])==0 || mpz_sgn(tab[0])==0){ fprintf(stderr, "Error in refinement (pos. roots): these values should not be zero\n"); exit(1); } long d = 1 + ilog2_mpz(rt->numer) - rt->k; /* fprintf(stderr, "[%d, %ld]", prec, prec + ((*deg) * MAX(0, 1 + d)) / 32); */ refine_QIR_positive_root(upol, deg, rt, tab, prec + (((*deg) - 1) * MAX(0, 1 + d)) / 32, verbose); if(mpz_sgn(tab[0])==mpz_sgn(tab[1])){ fprintf(stderr,"BUG in refinement (sgn tab[0]=sgn tab[1] for pos. roots)"); exit(1); } if(rt->isexact==1){ if(rt->k < 0){ rt->k = 0; } } } e_time += realtime() - refine_time; if(e_time>=step){ refine_time = realtime(); e_time = 0; if(verbose>=1){ fprintf(stderr, "{%.2f%s}", ((double)(i) / nb) * 100, "%"); } } } if(verbose>=1){ fprintf(stderr, "\n"); } for(i = 0; i < 8; i++){ mpz_clear(tab[i]); } free(tab); } void refine_all_roots_naive(mpz_t *upol, unsigned long int deg, interval *roots, unsigned long int nb, unsigned int prec, int calgo, int debug){ mpz_t *middle=malloc(sizeof(mpz_t)); mpz_init(middle[0]); for(unsigned long int j = 0; j < nb; j++){ while((roots+j)->k < prec && (roots+j)->isexact == 0){ refine_root_naive(upol, deg, roots+j, middle, calgo); } } mpz_clear(middle[0]); free(middle); } msolve-0.6.5/src/usolve/refine.h000066400000000000000000000020051456710632100165560ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifndef USOLVE #define USOLVE #endif void USOLVErefine_all_roots_naive(mpz_t *, unsigned long int, interval *, unsigned long int, unsigned int, int, int); void USOLVErefine_QIR_roots(mpz_t *, unsigned long int *, interval *, int, int, int, int, double, int); msolve-0.6.5/src/usolve/taylor_shift.c000066400000000000000000000270151456710632100200200ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include "univmultiply.c" #ifndef USOLVE #define USOLVE #endif static void mpz_poly_add(mpz_t *res, mpz_t *upol1, const unsigned long int deg1, mpz_t *upol2, const unsigned long int deg2){ if(deg1 > deg2){ mpz_poly_add(res, upol2, deg2, upol1, deg1); return; } for(unsigned long int i = 0; i <= deg1; i++){ mpz_add(res[i], upol1[i], upol2[i]); } for(unsigned long int i = deg1 + 1;i <= deg2; i++){ mpz_set(res[i],upol2[i]); } } /*naive taylor shift by 1 (in place)*/ static void taylorshift1_naive(mpz_t *upol, const unsigned long int deg){ long int i,j; for (i = 0; i <= deg-1; i++){ for (j = deg-1 ; j >= i; j--){ mpz_add(upol[j], upol[j], upol[j+1]); } } } static inline void mpz_poly_swap_th(mpz_t *res, mpz_t *pol, const unsigned long int deg, const unsigned int nthreads){ #ifdef _OPENMP omp_set_num_threads(nthreads); #endif #pragma omp parallel for num_threads(nthreads) for(unsigned long int i = 0; i <= deg; i++){ mpz_swap(res[i], pol[i]); } } static inline void mpz_poly_add_th(mpz_t *res, mpz_t *upol1, const unsigned long int deg1, mpz_t *upol2, const unsigned long int deg2, const unsigned int nthreads){ if(deg1 > deg2){ mpz_poly_add(res, upol2, deg2, upol1, deg1); return; } unsigned long int i; #ifdef _OPENMP omp_set_num_threads(nthreads); #endif #pragma omp parallel for num_threads(nthreads) //schedule(static) for(i = 0; i <= deg1; i++){ mpz_add(res[i], upol1[i], upol2[i]); } #pragma omp parallel for num_threads(nthreads) //schedule(static) for(i = deg1 + 1; i <= deg2; i++){ mpz_set(res[i],upol2[i]); } } static void rescale_upoly_2exp(mpz_t *upol, const unsigned long int deg, const unsigned long int content){ if(content==0){ return; } for(unsigned long int i = 0; i <= deg; i++){ mpz_mul_2exp(upol[i], upol[i], content); } } //pol : polynome //deg : degre(pol) //tmpol : polynome de degre deg -- sert de tmpol //shift_pwx : tableau de polynome //le premier est de degre size, le second 2*size, le troisieme 4*size etc. //le dernier est de degre 2^l*size avec l le plus grand possible tel que //2^(l*size) est inferieur a deg. //nblocks doit etre la plus petite puissance de 2 qui divise deg/size. //on a pol = pol1+X^size*pol2+X^(2*size)*pol3+X^(3*size)*pol4+... //pol0, pol1, etc. sont de degre size-1 sauf le dernier qui est de degre //final_degree //Ainsi on a : pol = [pol_1, pol_2, ..., pol_k] //deg(pol_i)=size-1 pour i c'est nblocks. //On fait le Taylor shift sur chaque bloc pol0, pol1, etc. //On note TL la fonction TaylorShift //On a maintenant //pol = [TL(pol_1), TL(pol_2), ..., TL(pol_k)] //ce sont les nouveaux pol_1, pol_2, etc. //On calcule (X+1)^size*pol_2, (X+1)^size*pol_2, (X+1)^size*pol_4, ... //tous les blocs pairs //ce sont des polynomes de degre 2*power-1 //sauf le derner qui est de degre size+final_degree //tmpol = [tmpol_1, tmpol_2, tmpol_3, tmpol_4, ... tmpol_{k/2}] //avec tmpol_i=pol_{2*i} * (X+1)^size donc tous de degre 2*size-1 sauf //le dernier qui est de degre final_degree+size static void taylorshift1_dac(mpz_t *upol, const unsigned long int deg, mpz_t *tmpol, mpz_t **shift_pwx, unsigned long int sz, const unsigned int nthreads){ int l; unsigned long int nblocks; if(deg <= sz){ nblocks=0; } else{ l = LOG2(deg / sz); nblocks = 1<1){ fdeg = deg - (nblocks-1)*sz; } else{ fdeg = deg - sz; } nblocks = nblocks / 2; for(int count = 1; count <= nblocks ; count++){ unsigned long int newdeg; if(count == nblocks){ newdeg = fdeg; } else{ newdeg = sz - 1; } cont2 = mpz_poly_remove_binary_content(upol + 2*(count-1)*sz+sz, newdeg); mpz_poly_mul(&tmpol[2*(count-1)*sz], shifted, sz, &upol[2*(count-1)*sz+sz], newdeg, nthreads); rescale_upoly_2exp(upol + 2*(count-1)*sz + sz, newdeg, cont2); rescale_upoly_2exp(tmpol + 2*(count-1)*sz, newdeg + sz, cont2); mpz_poly_add_th(&upol[2*(count-1)*sz], &upol[2*(count-1)*sz], sz-1, &tmpol[2*(count-1)*sz], sz-1, nthreads); mpz_poly_swap_th(&upol[2*(count-1)*sz+sz], &tmpol[2*(count-1)*sz + sz], newdeg, nthreads); } sz = 2 * sz; fdeg = deg - (nblocks-1)*sz; } fdeg = deg - sz; shifted = shift_pwx[npowers-1]; cont2 = mpz_poly_remove_binary_content(upol + sz, fdeg); mpz_poly_mul(tmpol, shifted, sz, upol+sz, fdeg, nthreads); rescale_upoly_2exp(upol + sz, fdeg, cont2); rescale_upoly_2exp(tmpol, fdeg + sz, cont2); mpz_poly_add_th(upol, upol, sz - 1, tmpol, sz - 1,nthreads); mpz_poly_swap_th(upol+sz, tmpol+sz, fdeg, nthreads); } static inline void decompose_bits_poly(mpz_t **upols, mpz_t *upol, const unsigned long int deg, const long int cutoff, const long int nbits, const long int nblocks){ for(long int j = nblocks - 1; j >= 0; j--){ long int trunc = nbits - cutoff * (nblocks - j); if(trunc < 0) trunc = 0; /* #pragma omp parallel for num_threads(nblocks) */ for(unsigned long int i = 0; i <= deg; i++){ mpz_tdiv_q_2exp(upols[j][i], upol[i], trunc); mpz_tdiv_r_2exp(upol[i], upol[i], trunc); } } } static long mpz_poly_sgn_variations_coeffs_bsize_with_index(mpz_t* upol, const unsigned long deg, const unsigned long int bsize, unsigned long int *index){ int s = mpz_sgn(upol[deg]); if(s==0){ return -1; } unsigned long int i; long nb = 0; int boo = 1; unsigned long int N = 1; int L = LOG2(bsize); for(i = deg - 1; i > 0; i--){ int c = mpz_cmp_ui(upol[i],0); long int l = ilog2_mpz(upol[i]); N = min((bsize - i +1)*L + 1, min(deg, (i+1)*L + 1)); if(l <= N || c==0){ boo = 0; } if( mpz_sgn(upol[i]) * s < 0 && l > N && c!=0){ nb = nb + 1; s = mpz_sgn(upol[i]); if(nb >= 3){ *index = i; return nb; } } } /* int oldnb = nb; */ N = L + 1; int c = mpz_cmp_ui(upol[0],0); long int l = ilog2_mpz(upol[0]); if(l <= N || c==0){ boo = 0; } if(s*mpz_sgn(upol[0]) < 0 && l> N && c!=0){ nb = nb + 1; } if(nb>=3 || boo == 1){ *index = i; return nb; } return -1; } /* This is called to perform a Taylor shift after truncation of coefficients of pol by maxnbits - 2*(deg + 1). Hence the first deg bits of the computed Taylor shifts are correct (actually, the sgn variation count functions use a more accurate estimate) */ static long taylorshift1_dac_wsgnvar(mpz_t *pol, const unsigned long int deg, mpz_t *tmpol, mpz_t **shift_pwx, unsigned long int pwx, const unsigned int nthreads){ /* nblocks is the largest power of 2 dividing deg / pwx */ int l ; unsigned long int nblocks ; if(deg <= pwx){ nblocks=0; } else{ l = LOG2(deg / pwx); nblocks = 1<1){ fdeg = deg - (nblocks-1)*pwx; } else{ fdeg = deg - pwx; } nblocks = nblocks / 2; for(int count=nblocks; count >= 1 ; count--){ unsigned long int ndeg; if(count==nblocks){ ndeg = fdeg; } else{ ndeg = pwx - 1; } mpz_poly_mul(&tmpol[2*(count-1)*pwx], current_shifted_powerX, pwx, &pol[2*(count-1)*pwx+pwx], ndeg, nthreads); mpz_poly_add_th(&pol[2*(count-1)*pwx], &pol[2*(count-1)*pwx], pwx-1, &tmpol[2*(count-1)*pwx], pwx-1, nthreads); mpz_poly_swap_th(&pol[2*(count-1)*pwx+pwx], &tmpol[2*(count-1)*pwx + pwx], ndeg, nthreads); } pwx = 2 * pwx; fdeg = deg - (nblocks-1)*pwx; } fdeg = deg - pwx; current_shifted_powerX = shift_pwx[npwr-1]; mpz_poly_mul(tmpol, current_shifted_powerX, pwx, pol+pwx, fdeg, nthreads); mpz_poly_add_th(pol, pol, pwx-1, tmpol, pwx-1,nthreads); mpz_poly_swap_th(pol+pwx, tmpol+pwx, fdeg, nthreads); unsigned long int index = 0; nb = mpz_poly_sgn_variations_coeffs_bsize_with_index(pol, deg, deg, &index); if(nb>=0) { return nb; } return -1; } msolve-0.6.5/src/usolve/taylor_shift.h000066400000000000000000000023331456710632100200210ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ //#include "utils.h" #include "univmultiply.h" #include "mpz_upoly_multiply.h" #define THRESHOLDSHIFT 256 //512 void taylorshift1_naive(mpz_t *, const unsigned long int); void taylorshift1_dac(mpz_t *, const unsigned long int, mpz_t *, mpz_t **, unsigned long int, const unsigned int); long USOLVEtaylor_shift_by_1_dac_wsgn_variations(mpz_t *, const unsigned long int, mpz_t *, mpz_t **, unsigned long int, const unsigned int); msolve-0.6.5/src/usolve/tests.c000066400000000000000000000531641456710632100164570ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include #include #include #include #include #include #ifdef _OPENMP #include #endif #include"taylor_shift.h" #include "flint/flint.h" #include "flint/fmpz.h" #include "flint/nmod_poly.h" #undef THRESHOLDSHIFT #define THRESHOLDSHIFT 512 #define BITSPRIME 64 static inline void compute_shift_pwx(mpz_t **shift_pwx, const unsigned long int deg, const unsigned long int npwr, unsigned long int pwx, const unsigned int nthreads){ taylorshift1_naive(shift_pwx[0], pwx); for(unsigned long int i=1; i=THRESHOLDSHIFT){ degpower = degpower / 2; } return degpower; } //On alloue de quoi stocker X^alpha, X^(2alpha), X^(4*alpha) etc. //avec alpha = THRESHOLDSHIFT static inline void allocate_shift_pwx(mpz_t **shift_pwx, unsigned long int npwr, unsigned long int pwx){ //pwx c'est le degre du premier element de shift_pwx unsigned long int newpwx=pwx; mp_bitcnt_t nbits=LOG2(newpwx); for(int i=0;iclassical_algo==0){ flags->cur_deg = deg; flags->pwx = compute_degpower(flags->cur_deg); if(flags->pwx>=flags->cur_deg){ flags->nblocks = 0; flags->npwr=0; } else{ flags->nblocks = 1<pwx); flags->npwr=LOG2(flags->nblocks); } if(flags->npwr>0){ flags->shift_pwx=(mpz_t **)malloc(sizeof(mpz_t *)*(flags->npwr)); allocate_shift_pwx(flags->shift_pwx, flags->npwr, flags->pwx); compute_shift_pwx(flags->shift_pwx, flags->cur_deg, flags->npwr, flags->pwx, flags->nthreads); } else{ flags->shift_pwx = NULL; } flags->tmpol = (mpz_t *)(malloc(sizeof(mpz_t)*(deg+1))); for(int i=0; i<=deg; i++){ mpz_init(flags->tmpol[i]); } flags->tmpol_desc = (mpz_t *)(malloc(sizeof(mpz_t)*(deg+1))); for(int i=0; i<=deg; i++){ mpz_init(flags->tmpol_desc[i]); } } } static void free_heap_flags(usolve_flags *flags, unsigned long int deg){ if(flags->classical_algo == 0){ for(unsigned long int i=0; i<=deg;i++){ mpz_clear(flags->tmpol_desc[i]); mpz_clear(flags->tmpol[i]); } } } static void initialize_flags(usolve_flags *flags){ flags->search = 0; flags->prec_isole = 16; flags->precision_loss = 0; flags->bound_pos = 0; flags->bound_neg = 0; flags->sign = 0; flags->revert = 1; flags->hasrealroots = 0; flags->transl = 0; flags->node_looked = 0; flags->half_done = 0; flags->cur_deg = 0; flags->pwx = 0; flags->nblocks = 0; flags->npwr = 0; flags->shift_pwx = NULL; flags->tmpol = NULL; flags->tmpol_desc = NULL; flags->time_desc = 0; flags->time_shift = 0; flags->nthreads = 1; flags->verbose = 0; flags->binary_file = 0; flags->classical_algo = 0; flags->print_stats = 0; flags->debug = 0; } /* static unsigned long int mpz_poly_max_bsize_coeffs(mpz_t *upoly, unsigned long int deg){ */ /* unsigned long int max = 0, bs; */ /* for(int i=0 ; i<=deg; i++){ */ /* bs = ilog2_mpz(upoly[i]); */ /* if(bs>max){ */ /* max = bs; */ /* } */ /* } */ /* return max; */ /* } */ void mpz_multi_mod_ui(mp_limb_t * out, const mpz_t in, mp_srcptr primes, long num_primes) { long i; for (i = 0; i < num_primes; i++) { out[i] = mpz_fdiv_ui(in, primes[i]); } } static inline mp_limb_t mynmod_add(mp_limb_t a, mp_limb_t b, nmod_t mod) { const mp_limb_t neg = mod.n - a; return ((neg > b) ? (a + b) : b - neg); /* if (neg > b) */ /* return a + b; */ /* else */ /* return b - neg; */ } void nmod_poly_taylor_shift_naive(mp_ptr residue, unsigned long int deg, nmod_t mod){ long int i, j; for(i = 0; i <=deg -1; i++){ for(j = deg - 1; j >= i; j--){ residue[j] = mynmod_add(residue[j], residue[j+1], mod); } } } void nmod_upoly_taylor_shift(mp_ptr residue, unsigned long int deg, mp_ptr tmp, mp_ptr *residue_shift_pwx, unsigned long int pwx, nmod_t mod){ int l; long int nblocks; if(deg<=pwx){ nblocks = 0; } else{ l =LOG2(deg / pwx); nblocks = 1<1){ fdegree = deg - (nblocks -1) * pwx; } else{ fdegree = deg - pwx; } nblocks = nblocks / 2; for(int cnt = 1; cnt <= nblocks; cnt++){ unsigned long int ndeg; if(cnt==nblocks){ ndeg = fdegree; } else{ ndeg = pwx - 1; } _nmod_poly_mul(&tmp[2*(cnt-1)*pwx], &residue[2*(cnt-1)*pwx + pwx], ndeg + 1, cur_shifted_pX, pwx + 1, mod); _nmod_poly_add(&residue[2*(cnt-1)*pwx], &residue[2*(cnt-1)*pwx], pwx, &tmp[2*(cnt-1)*pwx], pwx, mod); } pwx = 2 * pwx; } return; } //NON FINIE CAR UNE ANALYSE DE COMPLEXITE MONTRE QUE CE N'EST PAS UTILE void multi_mod_taylor_shift(mpz_t *pol, unsigned long int deg, mpz_t **shift_pwx, unsigned long int pwx, int nthreads){ unsigned long int nbits = USOLVEmpz_poly_max_bsize_coeffs(pol, deg); fprintf(stderr, "nbits = %lu\n", nbits); nbits = nbits + deg + 1 + LOG2(deg + 1); fprintf(stderr, "nbits = %lu\n", nbits); /* gets primes between 2^63 and 2^64 */ unsigned long int nprimes = (nbits + (BITSPRIME - 1) - 1) / (BITSPRIME - 1); mp_ptr primes = malloc(sizeof(mp_limb_t) * nprimes); fprintf(stderr, "%lu\n", UWORD(1) << (BITSPRIME - 1)); primes[0] = n_nextprime(UWORD(1) << (BITSPRIME - 1), 1); for (unsigned long int i = 1; i < nprimes; i++) primes[i] = n_nextprime(primes[i-1], 1); //allocates space for pol modulo the primes mp_ptr *residues = malloc(sizeof(mp_ptr) * nprimes); for(unsigned long int i = 0; i < nprimes; i++){ residues[i] = malloc(sizeof(mp_limb_t) * (deg + 1)); } fprintf(stderr, "nprimes = %lu\n", nprimes); //allocates space for shiftedpowers of X unsigned long int nblocks = 1<primes, comb->num_primes); for (unsigned long i = 0; i < nprimes; i++) // residues[i][j] = mpz_fdiv_ui(pol[j], primes[i]); residues[i][j] = mpz_fdiv_ui(pol[j], primes[i]); } fprintf(stderr, "Residues loaded (%f sec)\n", realtime() - e); for(unsigned long int i = 0; i < nprimes; i++){ nmod_t mod; mp_limb_t p; p = primes[i]; nmod_init(&mod, p); nmod_upoly_taylor_shift(residues[i], deg, tmp_pol, residues_shift_pwx[i], pwx, mod); } fprintf(stderr, "Time multimod = %f\n", realtime() - e); free(tmp); for(unsigned long int i = 0; i < nprimes; i++){ free(residues[i]); } free(residues); free(primes); return; } /* pol = pols[0] + 2^sb pols [1] + 2^(2*sb) pols[2] + ... + 2^(sb * (nthreads - 1)) * pols[nthreads - 1] */ void split_coeffs_poly(mpz_t **pols, mpz_t * pol, unsigned long int deg, long int nbits, int nthreads){ for(int j = nthreads - 1; j >= 0; j--){ long int trunc = j * nbits / nthreads ; #pragma omp parallel for num_threads(nthreads) for(unsigned long int i = 0; i <= deg; i++){ mpz_tdiv_q_2exp(pols[j][i], pol[i], trunc); mpz_tdiv_r_2exp(pol[i], pol[i], trunc); } } } //tbr == to be removed //Ici, on recupere la taille binaire max "nbits" de pol //ensuite on ecrit pol = pol0+ 2^q * pol1 + ...+ 2^(q * nthreads) * pol_n //ou q = nbits / nthreads void tbr_taylor_shift(mpz_t *pol, unsigned long int deg, mpz_t **tmp, mpz_t **pols, mpz_t **shift_pwx, unsigned long int pwx, int nthreads){ long int nbits = USOLVEmpz_poly_max_bsize_coeffs(pol, deg); // mpz_poly_print_maple(pol, deg); // long int sb = 2 * nbits / (nthreads * deg); // fprintf(stderr, "[sb = %ld]\n", sb); if(nthreads >= 1){ // fprintf(stderr, "New algo starts\n"); split_coeffs_poly(pols, pol, deg, nbits, nthreads); //double e = realtime(); #pragma omp parallel for num_threads(nthreads) for(int j = 0; j < nthreads; j++){ // fprintf(stderr, "bs = %ld\n", mpz_poly_max_bsize_coeffs(pols[j], deg)); // mpz_poly_print_maple(pols[j], deg); taylorshift1_dac(pols[j], deg, tmp[j], shift_pwx, pwx, 0); } // fprintf(stderr, "time %f\n", realtime() - e); // e = realtime(); #pragma omp parallel for num_threads(nthreads) for(int j = 0; j < nthreads; j++){ int trunc = j * nbits / nthreads; for(unsigned long int i = 0; i <= deg; i++){ mpz_mul_2exp(pols[j][i], pols[j][i], trunc); } } // fprintf(stderr, "Rescaling done (time = %f)\n", realtime() - e); #pragma omp parallel for num_threads(nthreads) for(unsigned long int i = 0; i <= deg; i++){ mpz_set_ui(pol[i], 0); for(int j = 0; j < nthreads; j++){ mpz_add(pol[i], pol[i], pols[j][i]); } } /* for(unsigned long int i = 0; i <= deg; i++){ */ /* mpz_set_ui(pol[i], 0); */ /* } */ /* for(int j = 0; j < nthreads; j++){ */ /* #pragma omp parallel for num_threads(nthreads) */ /* for(unsigned long int i = 0; i <= deg; i++) */ /* mpz_add(pol[i], pol[i], pols[j][i]); */ /* } */ } else{ taylorshift1_dac(pol, deg, tmp[0], shift_pwx, pwx, nthreads); } } static inline void decompose_bits_poly(mpz_t **pols, mpz_t *pol, unsigned long int deg, long int cutoff, long int nbits, long int nblocks){ for(long int j = nblocks - 1; j >= 0; j--){ long int trunc = nbits - cutoff * (nblocks - j); if(trunc < 0) trunc = 0; //#pragma omp parallel for num_threads(nblocks) for(unsigned long int i = 0; i <= deg; i++){ mpz_tdiv_q_2exp(pols[j][i], pol[i], trunc); mpz_tdiv_r_2exp(pol[i], pol[i], trunc); } } } void taylor_shift(mpz_t *pol, unsigned long int deg, mpz_t **tmp, mpz_t **pols, mpz_t **shift_pwx, unsigned long int pwx, int nthreads){ long int nbits = USOLVEmpz_poly_max_bsize_coeffs(pol, deg); long int cutoff = 2 * deg ; long int nblocks = nbits / cutoff + 1; double e = 0, tmp_e; for(unsigned long int i = 0; i <= deg; i++){ mpz_set_ui(tmp[nthreads][i], 0); } if(nthreads >= 1 && nblocks > 0){ if(nblocks <= nthreads){ fprintf(stderr, "nblocks (%ld) <= nthreads (%d)\n", nblocks, nthreads); // long int nt = nthreads / nblocks; //pol = pols[0] + 2^(2*deg) * pols[1] + 2^(4*deg) * pols[2] + 2^(6*deg) *pols[3] +...+2^(nblocks*2*deg)*pols[nblocks] decompose_bits_poly(pols, pol, deg, cutoff, nbits, nblocks); // e = realtime(); //#pragma omp parallel { //#pragma omp parallel for num_threads(nthreads) schedule(dynamic) #pragma omp parallel for schedule(dynamic) for(int j = 0; j < nblocks; j++){ // fprintf(stderr, "bs = %ld\n", mpz_poly_max_bsize_coeffs(pols[j], deg)); mpz_t *local_pol = pols[j]; mpz_t *local_tmp = tmp[j]; taylorshift1_dac(local_pol, deg, local_tmp, shift_pwx, pwx, 1); } } // fprintf(stderr, "time %f\n", realtime() - e); // mpz_poly_print_maple(pols[0], deg); // e = realtime(); for(long int j = nblocks-1; j >=0; j--){ long int trunc = nbits - cutoff * (nblocks - j); if(trunc < 0) trunc = 0; for(unsigned long int i = 0; i <= deg; i++){ mpz_mul_2exp(pols[j][i], pols[j][i], trunc); } } mpz_t *local_tmp = tmp[nthreads]; for(int j = 0; j < nblocks; j++){ //#pragma omp parallel for num_threads(nthreads) for(unsigned long int i = 0; i <= deg; i++){ mpz_add(local_tmp[i], local_tmp[i], pols[j][i]); } } for(unsigned long int i = 0; i <= deg; i++){ mpz_set(pol[i], local_tmp[i]); } return; } else{//nblocks > nthreads fprintf(stderr, "nblocks (%ld) > nthreads (%d)\n", nblocks, nthreads); //nblocks = nbits / cutoff long int q = nblocks / nthreads ;//pb quand nthreads = 1 (doit prendre q+1) if(nthreads==1){ // q++; } while(q){ tmp_e = realtime(); decompose_bits_poly(pols, pol, deg, cutoff, nbits, nthreads); e += (realtime() - tmp_e); // tmp_e = realtime(); #pragma omp parallel for num_threads(nthreads) for(int j = 0; j < nthreads; j++){ taylorshift1_dac(pols[j], deg, tmp[j], shift_pwx, pwx, 1); } for(long int j = nthreads - 1; j >= 0; j--){ long int trunc = nbits - cutoff * (nthreads - j); if(trunc < 0) trunc = 0; #pragma omp parallel for num_threads(nthreads) for(unsigned long int i = 0; i <= deg; i++){ mpz_mul_2exp(pols[j][i], pols[j][i], trunc); } } #pragma omp parallel for num_threads(nthreads) for(unsigned long int i = 0; i <= deg; i++){ for(int j = 0; j < nthreads; j++){ mpz_add(tmp[nthreads][i], tmp[nthreads][i], pols[j][i]); } } // e+=realtime() - tmp_e; nbits -= cutoff * nthreads; q--; } // fprintf(stderr, "time = %f\n", e); long rth = nblocks % nthreads + 1; if(rth==0){ for(unsigned long int i = 0; i <= deg; i++){ mpz_swap(pol[i], tmp[nthreads][i]); } return; } tmp_e = realtime(); decompose_bits_poly(pols, pol, deg, cutoff, nbits, rth); e += (realtime() - tmp_e); // fprintf(stderr, "time in decompose_bits_poly = %f\n", e); // e = realtime(); //#pragma omp parallel for num_threads(rth) for(int j = 0; j < rth; j++){ taylorshift1_dac(pols[j], deg, tmp[j], shift_pwx, pwx, nthreads); } for(int j = rth - 1; j >= 0; j--){ int trunc = nbits - cutoff * (rth - j); if(trunc < 0) trunc = 0; for(unsigned long int i = 0; i <= deg; i++){ mpz_mul_2exp(pols[j][i], pols[j][i], trunc); } } #pragma omp parallel for num_threads(nthreads) for(unsigned long int i = 0; i <= deg; i++){ for(int j = 0; j < rth; j++){ mpz_add(tmp[nthreads][i], tmp[nthreads][i], pols[j][i]); } mpz_swap(pol[i], tmp[nthreads][i]); } return; } } else{ taylorshift1_dac(pol, deg, tmp[0], shift_pwx, pwx, nthreads); } } int main(int argc, char **argv){ if(argc!=5){ fprintf(stderr, "Runs taylor shifts and measures timings\n"); fprintf(stderr, "Usage is %s \n", argv[0]); exit(1); } unsigned long int deg = atoi(argv[1]); unsigned long int nbits = atoi(argv[2]); int nthreads = atoi(argv[3]); mpz_t * pol1 = (mpz_t *)malloc((deg + 1) * sizeof(mpz_t)); mpz_t * pol2 = (mpz_t *)malloc((deg + 1) * sizeof(mpz_t)); mpz_t * pol3 = (mpz_t *)malloc((deg + 1) * sizeof(mpz_t)); mpz_t * tmpol = (mpz_t *)malloc((deg + 1) * sizeof(mpz_t)); for(unsigned long int i = 0; i <= deg; i++){ mpz_init(pol1[i]); mpz_init(pol2[i]); mpz_init(pol3[i]); mpz_init2(tmpol[i], deg + nbits); } usolve_flags *flags = (usolve_flags*)(malloc(sizeof(usolve_flags))); fprintf(stderr, "Starting initialization of data\n"); double t = realtime(); initialize_flags(flags); initialize_heap_flags(flags, deg); fprintf(stderr, "Time for initialization = %f\n", realtime()-t); mpz_random_dense_poly(pol1, deg, nbits); // USOLVEmpz_poly_print_maple(pol1, deg); for(unsigned long int i = 0; i <= deg; i++){ mpz_set(pol2[i], pol1[i]); mpz_set(pol3[i], pol1[i]); } int nloops = atoi(argv[4]); fprintf(stderr, "nloops = %d\n\n", nloops); double e_time = realtime(); for(unsigned long int i = 0; i <= deg; i++){ mpz_set(pol1[i], pol2[i]); } e_time = realtime(); for(int i = 0; i < nloops; i++) taylorshift1_dac(pol1, deg, tmpol, flags->shift_pwx, flags->pwx, nthreads); fprintf(stdout, "Elapsed time %f (Taylor shift Usolve nthreads = %d)\n", realtime() - e_time, nthreads); mpz_t **tmp = malloc(sizeof(mpz_t *) * (nthreads + 1)); mpz_t **pols = malloc(sizeof(mpz_t *) * nthreads); fprintf(stderr, "Allocation starts\n"); for(int i = 0; i <= nthreads; i++){ tmp[i] = (mpz_t *)malloc((deg + 1) * sizeof(mpz_t)); for(unsigned long int j = 0; j <= deg; j++){ mpz_init2(tmp[i][j], 2 * deg); } } for(int i = 0; i < nthreads; i++){ pols[i] = (mpz_t *)malloc((deg + 1) * sizeof(mpz_t)); for(unsigned long int j = 0; j <= deg; j++){ mpz_init2(pols[i][j], 2 * deg); } } fprintf(stderr, "Allocation done\n\n"); e_time = realtime(); for(int i=0; i < nloops; i++) tbr_taylor_shift(pol2, deg, tmp, pols, flags->shift_pwx, flags->pwx, nthreads); fprintf(stdout, "Elapsed time (New TBR_Taylor shift with nthreads = %d) %f\n\n", nthreads, realtime() - e_time); e_time = realtime(); for(int i=0; i < nloops; i++) taylor_shift(pol3, deg, tmp, pols, flags->shift_pwx, flags->pwx, nthreads); fprintf(stdout, "Elapsed time (New Taylor shift not in Usolve yet with nthreads = %d) %f\n\n", nthreads, realtime() - e_time); for(int i = 0; i < nthreads; i++){ for(unsigned long int j = 0; j <= deg; j++){ mpz_clear(tmp[i][j]); mpz_clear(pols[i][j]); } free(tmp[i]); free(pols[i]); } free(tmp); free(pols); for(unsigned long i=0; i <= deg; i++){ if(mpz_cmp(pol1[i], pol2[i])!=0){ fprintf(stderr, "BUG in TBR\n\n"); return 1; } if(mpz_cmp(pol1[i], pol3[i])!=0){ fprintf(stderr, "BUG in TL\n\n"); return 1; } } for(unsigned long int i = 0; i <= deg; i++){ mpz_clear(pol1[i]); mpz_clear(pol2[i]); mpz_clear(pol3[i]); mpz_clear(tmpol[i]); } free_heap_flags(flags, deg); free(pol1); free(pol2); free(pol3); free(tmpol); return 1; } msolve-0.6.5/src/usolve/univmultiply.c000066400000000000000000000063051456710632100200710ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #ifdef _OPENMP #include #endif #define USEFLINT 1 #ifdef USEFLINT #include "flint/flint.h" #include "flint/fmpz.h" #include "flint/fft.h" #include "flint/fft_tuning.h" #include "flint/fmpz_poly.h" #else #include"mpz_upoly_multiply.h" #endif #ifdef USEFLINT void fmpz_poly_set_coeff_mpz2(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); } /* from mpz_t *poly to fmpz_poly_t */ static void mpz_2_fmpz_poly(fmpz_poly_t poly_flint, const mpz_t *poly_gmp, const unsigned long int deg, const unsigned int nthreads){ poly_flint->length = deg + 1; poly_flint->alloc = deg + 1; unsigned long int i; #pragma omp parallel for private(i) num_threads(nthreads) for(i = 0; i <= deg; i++){ fmpz_poly_set_coeff_mpz2(poly_flint, ((slong)i),poly_gmp[i]); } } /* from fmpz_poly_t to mpz_t *poly */ /* poly must have been allocated */ static void fmpz_poly_2_mpz(mpz_t *poly_gmp, const fmpz_poly_t poly_flint, const unsigned long int deg, const unsigned int nthreads){ unsigned long int i; #pragma omp parallel for private(i) num_threads(nthreads) for(i = 0; i <= deg; i++){ fmpz_get_mpz(poly_gmp[i],(poly_flint->coeffs + i)); } } #endif /* res will contain pol1 * pol2 */ /* pol1 has degree deg1 and pol2 has degree deg2 */ /* res must be already allocated */ static void mpz_poly_mul(mpz_t *res, const mpz_t *pol1, const unsigned long int deg1, const mpz_t *pol2, const unsigned long int deg2, const unsigned int nthreads){ #ifdef USEFLINT fmpz_poly_t res_fmpz_poly; fmpz_poly_t pol1_fmpz_poly; fmpz_poly_t pol2_fmpz_poly; fmpz_poly_init2(res_fmpz_poly, deg1+deg2+1); fmpz_poly_init2(pol1_fmpz_poly, deg1+1); fmpz_poly_init2(pol2_fmpz_poly, deg2+1); mpz_2_fmpz_poly(pol1_fmpz_poly, pol1, deg1, nthreads); mpz_2_fmpz_poly(pol2_fmpz_poly, pol2, deg2, nthreads); flint_set_num_threads(nthreads); fmpz_poly_mul(res_fmpz_poly, pol2_fmpz_poly, pol1_fmpz_poly); fmpz_poly_2_mpz(res, res_fmpz_poly, deg1+deg2, nthreads); fmpz_poly_clear(res_fmpz_poly); fmpz_poly_clear(pol1_fmpz_poly); fmpz_poly_clear(pol2_fmpz_poly); #else fprintf(stderr, "FLINT is missing for univariate polynomial multiplication\n"); exit(1); #endif } msolve-0.6.5/src/usolve/univmultiply.h000066400000000000000000000024621456710632100200760ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include #include #include #include #include #include void mpz_poly_mul(mpz_t *, mpz_t *, unsigned long int, mpz_t *, unsigned long int, unsigned int); #ifdef USEFLINT void mpz_poly_mul_allocated_fmpz_poly(mpz_t *, mpz_t *, unsigned long int, mpz_t *, unsigned long int, fmpz_poly_t, fmpz_poly_t, fmpz_poly_t); void mpz_upoly_mul(mpz_t *, mpz_t *, mpz_t *, unsigned long int, unsigned long int, fmpz_poly_t, fmpz_poly_t, fmpz_poly_t, int); #endif msolve-0.6.5/src/usolve/usolve.c000066400000000000000000001066231456710632100166310ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #ifdef _OPENMP #include #endif /* for timing functions */ #include "../neogb/tools.h" #include "flint/flint.h" #include "flint/fmpz.h" #include "flint/fmpz_poly.h" #include "../msolve/msolve-data.h" #define THRESHOLDSHIFT 256 #define POWER_HACK 1 #define ilog2(a) mpz_sizeinbase(a,2) #define LOG2(X) ((unsigned) (8*sizeof (unsigned long long) - __builtin_clzll((X)) - 1)) #define ilog2_mpz(a) mpz_sizeinbase(a,2) #define min(a, b) (((a) < (b)) ? (a) : (b)) #ifndef MAX #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif #include "data_usolve.c" #include "utils.c" #include "taylor_shift.c" #include "descartes.c" #include "evaluate.c" #include "print_usolve.c" #include "refine.c" static long bisection_rec(mpz_t *, unsigned long *, mpz_t, long, interval *, unsigned long int *, usolve_flags *, mpz_t); /* Kioustelidis's bound : 2*max(abs(-ai/an)^(1/(n-i)), the maximum being taken over the i with sgn(a_i) != sgn(an) */ /* Computes M such that 2^M is greater than Kioustelidis's bound */ /* which is 2*max(abs(-ci/cn)^(1/(n-i)) for those i's such that sign(ci) != sign(c[deg])*/ /* (the ci's are the coefficients of upol) */ /* returns -1 if there is obviously no positive root */ static long bound_roots(mpz_t *upol, const unsigned long deg){ int b = 1; /* 2^l < c[deg] < 2^(l+1)*/ const long l = ilog2(upol[deg]) - 1; long M = -l; for(unsigned long int i = 0; i < deg; i++){ long pow, pow2; if (mpz_sgn(upol[deg]) != mpz_sgn(upol[i])){ b = 0; pow = ilog2(upol[i]) ; pow -= l; /* 2^currpow >= abs(-ai/an) */ if(pow > 0){ pow2 = pow / (deg - i); } else{ pow2 = -((-pow) / (deg - i)); } if(pow2 * ((long) (deg - i)) != pow){ pow2++; } if(pow2 > M){ M = pow2; } } } /* there can't be positive roots */ if (b == 1) return -1; M++; return M; } static inline void compute_shift_pwx(mpz_t **shifted, const unsigned long int deg, const unsigned long int npwr, unsigned long int pwx, const unsigned int nthreads){ taylorshift1_naive(shifted[0], pwx); for(unsigned long int i=1; i < npwr; i++){ mpz_poly_mul(shifted[i], shifted[i-1], pwx, shifted[i-1], pwx, nthreads); pwx = 2 * pwx; } } static unsigned long int compute_degpower(const unsigned long int deg){ unsigned long int pwr=deg; while(pwr-1 >= THRESHOLDSHIFT){ pwr = pwr / 2; } return pwr; } static void assign_sign_left(interval *roots, const unsigned long int nbneg, const unsigned long int nbpos, const int b){ int s = b; for(unsigned long int i = 0; i < nbneg; i++){ (roots+i)->sign_left = s; s=-s; } for(unsigned long int i = nbneg; i < nbpos; i++){ (roots+i)->sign_left = s; s=-s; } } static void merge_root(interval *roots, mpz_t c, long k, const unsigned int isexact, const int sgnlft, const unsigned long int nb, const int b_pos, const int b_neg, const int sgn){ int b; if(sgn >0){ b = b_neg; } else{ b = b_pos; } mpz_init(roots[nb].numer); if (k <= b) { if (sgn){ mpz_neg(roots[nb].numer, c); if (!isexact){ mpz_sub_ui(roots[nb].numer, roots[nb].numer, 1); } mpz_mul_2exp(roots[nb].numer, roots[nb].numer, b-k); } else{ mpz_mul_2exp(roots[nb].numer, c, b-k); } roots[nb].isexact = isexact; if(roots[nb].isexact==1){ roots[nb].k = 0; } else{ roots[nb].k = k - b; } roots[nb].sign_left = sgnlft; return; } else { if (sgn){ mpz_neg(roots[nb].numer, c); if (!isexact) mpz_sub_ui(roots[nb].numer, roots[nb].numer, 1); } else{ mpz_set(roots[nb].numer, c); } roots[nb].k = k - b; roots[nb].isexact = isexact; roots[nb].sign_left = sgnlft; } return; } static inline void allocate_shift_pwx(mpz_t **shifted, const unsigned long int npwr, const unsigned long int pwx){ unsigned long int newpwx=pwx; mp_bitcnt_t nbits=LOG2(newpwx); for(int i = 0; i < npwr; i++){ shifted[i] = (mpz_t *)malloc(sizeof(mpz_t)*(newpwx+1)); for(int j = 0; j <= newpwx; j++){ mpz_init2(shifted[i][j], nbits); } newpwx = 2 * newpwx; nbits = LOG2(newpwx); } mpz_set_ui(shifted[0][pwx],1); } static inline void unallocate_shift_pwx(mpz_t **shifted, const unsigned long int npwr, unsigned long int pwx){ for(int i = 0; i < npwr; i++){ for(int j = 0;j <= pwx; j++){ mpz_clear(shifted[i][j]); } pwx=2*pwx; } for(int i = 0; i < npwr; i++){ free(shifted[i]); } } static inline long mpz_poly_sign_at_one(mpz_t *upol, const unsigned long int deg, mpz_t *vals){ mpz_set_ui(vals[0], 0); for(unsigned long int i=0; i <= deg; i++){ mpz_add(vals[0], vals[0],upol[i]); } return mpz_sgn(vals[0]); } /* assumes upol[0 != 0] */ static inline long mpz_poly_sgn_variations_coeffs_is_zero(mpz_t* upol, const unsigned long deg){ unsigned long int i; long nb = 0; int s = mpz_sgn(upol[deg]); for(i = deg - 1; i > 0; i--){ if( mpz_sgn(upol[i]) * s < 0 ){ nb = nb + 1; s = mpz_sgn(upol[i]); if(nb >= 1){ return nb; } } } if(s * mpz_sgn(upol[0]) < 0){ nb = nb + 1; } return nb; } /* if 0 is a root, adds c / 2^k to the array of roots and update upol */ static void is_zero_root(mpz_t *upol, mpz_t c, long k, unsigned long *deg, interval *roots, unsigned long int *nbroot, usolve_flags *flags){ unsigned long int i, j; if(mpz_cmp_ui(upol[0], 0) == 0){ i = 1; while(mpz_cmp_ui(upol[i], 0) == 0){ i++; } if(i >= 2){ fprintf(stderr, "error: the polynomial is not square-free\n"); exit(1); } for(j = 0; j < i; j++){ merge_root(roots, c, k, 1, 0, *nbroot, flags->bound_pos, flags->bound_neg, flags->sign); (*nbroot) ++; } *deg -= i; for (j = 0; j <= *deg; j++, i++){ mpz_set(upol[j], upol[i]); } unsigned long int newpwx = compute_degpower(flags->cur_deg); if(newpwx != flags->pwx){ unallocate_shift_pwx(flags->shift_pwx, flags->npwr, flags->pwx); free(flags->shift_pwx); flags->pwx = newpwx; if(newpwx >= flags->cur_deg){ flags->nblocks = 0; flags->npwr= 0; } else{ flags->nblocks = 1<cur_deg/flags->pwx); flags->npwr=LOG2(flags->nblocks); } if(flags->npwr>0){ flags->shift_pwx=(mpz_t **)malloc(sizeof(mpz_t *)*(flags->npwr)); allocate_shift_pwx(flags->shift_pwx, flags->npwr, flags->pwx); compute_shift_pwx(flags->shift_pwx, flags->cur_deg, flags->npwr, flags->pwx, flags->nthreads); } else{ flags->shift_pwx = NULL; } } } } /* it returns the sign of upoly(1/2) */ static int sgn_mpz_upoly_eval_onehalf(mpz_t *upol, unsigned long int deg, usolve_flags *flags){ long i; mpz_set(flags->Values[0], upol[deg]); for (i = deg - 1; i >= 0; i--){ mpz_mul_2exp(flags->Values[1], upol[i], deg - i); mpz_add(flags->Values[0], flags->Values[0], flags->Values[1]); } i = mpz_sgn(flags->Values[0]); return i; } static void numer_quotient_uint(mpz_t *upol, unsigned long int *deg, unsigned int c, long k){ for(unsigned long int i = 0; i <= *deg; i++){ mpz_mul_2exp(upol[i], upol[i], (*deg - 1) * k ); } mpz_t tmp; mpz_init(tmp); for(long int i = *deg - 1; i >=1; i--){ mpz_div_2exp(tmp, upol[i+1], k); mpz_mul_ui(tmp, tmp, c); mpz_add(upol[i], upol[i], tmp); } for(long int i = 0 ; i <= *deg - 1; i++){ mpz_set(upol[i], upol[i+1]); } mpz_poly_remove_binary_content(upol, *deg-1); *deg = *deg - 1; mpz_clear(tmp); } static long int manage_root_at_one_half(mpz_t *upol, mpz_t c, long k, unsigned long *deg, mpz_t tmp, unsigned long int *nbr, usolve_flags *flags){ long int sh = sgn_mpz_upoly_eval_onehalf(upol, *deg, flags); while (sh == 0) { mpz_set(tmp, c); mpz_mul_2exp(tmp, tmp, 1); mpz_add_ui(tmp, tmp, 1); numer_quotient_uint(upol, deg, 1, 1); sh = sgn_mpz_upoly_eval_onehalf(upol, *deg, flags); flags->cur_deg = (*deg); if(sh == 0){ fprintf(stderr, "Input polynomial is not square-free\n"); exit(1); } unsigned long int newpwx = compute_degpower(flags->cur_deg); if(flags->classical_algo == 0 && newpwx !=flags->pwx){ unallocate_shift_pwx(flags->shift_pwx, flags->npwr, flags->pwx); free(flags->shift_pwx); flags->pwx = newpwx; if(newpwx>=flags->cur_deg){ flags->nblocks = 0; flags->npwr= 0; } else{ flags->nblocks = 1<cur_deg/flags->pwx); flags->npwr=LOG2(flags->nblocks); } if(flags->npwr>0){ flags->shift_pwx=(mpz_t **)malloc(sizeof(mpz_t *)*(flags->npwr)); allocate_shift_pwx(flags->shift_pwx, flags->npwr, flags->pwx); compute_shift_pwx(flags->shift_pwx, flags->cur_deg, flags->npwr, flags->pwx, flags->nthreads); } else{ flags->shift_pwx = NULL; } } } return sh; } static long nb_0_case_in_bisection_rec(const mpz_t c, const long k, mpz_t tmp, interval *roots, unsigned long int *nbr, usolve_flags *flags, const int is_half_root){ if(is_half_root){ mpz_set(tmp, c); mpz_mul_2exp(tmp, tmp, 1); mpz_add_ui(tmp, tmp, 1); merge_root(roots, tmp, k + 1, 1, 0, *nbr, flags->bound_pos, flags->bound_neg, flags->sign); (*nbr)++; if(flags->hasrealroots==1 && (*nbr)>0){ mpz_clear(tmp); return -1; } if(flags->verbose >= 1){ fprintf(stderr,"+"); if((*nbr) % 100 == 0) fprintf(stderr, "[%lu]",(*nbr)); } } if(flags->verbose >= 1){ fprintf(stderr,"!"); } mpz_clear(tmp); return k; } static long nb_1_case_in_bisection_rec(mpz_t c, const long k, mpz_t tmp, interval *roots, unsigned long int *nbr, usolve_flags *flags, const int is_half_root, const long bot, const long top, const long half){ if(is_half_root){ if(bot * half <0){ mpz_set(tmp, c); mpz_mul_2exp(tmp, tmp, 1); merge_root(roots, tmp, k+1, 0, bot, *nbr, flags->bound_pos, flags->bound_neg, flags->sign); (*nbr) ++; if(flags->verbose >= 1){ fprintf(stderr,"+"); if((*nbr) % 100 == 0) fprintf(stderr, "[%lu]",(*nbr)); } if(flags->hasrealroots == 1 && (*nbr)>0){ mpz_clear(tmp); return -1; } /* adds 1 / 2 */ mpz_add_ui(tmp, tmp, 1); merge_root(roots, tmp, k+1, 1, 0, *nbr, flags->bound_pos, flags->bound_neg, flags->sign); (*nbr)++; if(flags->verbose >= 1){ fprintf(stderr,"+"); if((*nbr) % 100 == 0) fprintf(stderr, "[%lu]",(*nbr)); } } else{ /* adds 1/ 2 */ mpz_set(tmp, c); mpz_mul_2exp(tmp, tmp, 1); mpz_add_ui(tmp, tmp, 1); merge_root(roots, tmp, k+1, 1, 0, *nbr, flags->bound_pos, flags->bound_neg, flags->sign); (*nbr)++; if(flags->verbose >= 1){ fprintf(stderr,"+"); if((*nbr) % 100 == 0) fprintf(stderr, "[%lu]",(*nbr)); } if(flags->hasrealroots==1 && (*nbr)>0){ mpz_clear(tmp); return -1; } if(top != 0){ /* 1 is not a root */ merge_root(roots, tmp, k+1, 0, half, *nbr, flags->bound_pos, flags->bound_neg, flags->sign); (*nbr)++; if(flags->verbose >= 1){ fprintf(stderr,"+"); if((*nbr) % 100 == 0) fprintf(stderr, "[%lu]",(*nbr)); } } else{ /* 1 is a root */ mpz_add_ui(tmp, tmp, 1); merge_root(roots, tmp, k+1, 1, 0, *nbr, flags->bound_pos, flags->bound_neg, flags->sign); (*nbr) ++; if(flags->verbose>=1){ fprintf(stderr,"+"); if((*nbr) % 100 == 0) fprintf(stderr, "[%lu]",(*nbr)); } if(flags->hasrealroots == 1 && (*nbr)>0){ mpz_clear(tmp); return -1; } } } } else{ if(top != 0){ merge_root(roots, c, k, 0, bot, *nbr, flags->bound_pos, flags->bound_neg, flags->sign); (*nbr)++; if(flags->verbose>=1){ fprintf(stderr,"+"); if((*nbr) % 100 == 0) fprintf(stderr, "[%lu]",(*nbr)); } if(flags->hasrealroots==1 && (*nbr)>0){ mpz_clear(tmp); return -1; } } else{ mpz_set(tmp, c); mpz_add_ui(tmp, tmp, 1); merge_root(roots, tmp, k, 1, 0, *nbr, flags->bound_pos, flags->bound_neg, flags->sign); (*nbr)++; if(flags->verbose >= 1){ fprintf(stderr,"+"); if((*nbr) % 100 == 0) fprintf(stderr, "[%lu]",(*nbr)); } if(flags->hasrealroots == 1 && (*nbr)>0){ mpz_clear(tmp); return -1; } } } mpz_clear(tmp); return k; } static long nb_2_case_in_bisection_rec(mpz_t c, const long k, mpz_t tmp, interval *roots, unsigned long int *nbr, usolve_flags *flags, const int is_half_root, const long bot, const long top, const long shalf){ //attention t peut etre egale a 0 mais 1/2 ne peut etre racine du polynome //courant (voir ci-dessus) (flags->half_done)++; mpz_set(tmp, c); mpz_mul_2exp(tmp, tmp, 1); merge_root(roots, tmp, k+1, 0, bot, *nbr, flags->bound_pos, flags->bound_neg, flags->sign); (*nbr)++; if(flags->verbose>=1){ fprintf(stderr,"+"); if((*nbr) % 100 == 0) fprintf(stderr, "[%lu]",(*nbr)); } if(flags->hasrealroots==1 && (*nbr)>0){ mpz_clear(tmp); return -1; } mpz_add_ui(tmp, tmp, 1); if(is_half_root){ merge_root(roots, tmp, k+1, 1, 0, *nbr, flags->bound_pos, flags->bound_neg, flags->sign); (*nbr)++; if(flags->verbose >= 1){ fprintf(stderr,"+"); if((*nbr) % 100 == 0) fprintf(stderr, "[%lu]",(*nbr)); } if(flags->hasrealroots==1 && (*nbr)>0){ mpz_clear(tmp); return -1; } } if(top != 0){ merge_root(roots, tmp, k+1, 0, shalf, *nbr, flags->bound_pos, flags->bound_neg, flags->sign); (*nbr) ++; if(flags->verbose >= 1){ fprintf(stderr,"+"); if((*nbr) % 100 == 0) fprintf(stderr, "[%lu]",(*nbr)); } if(flags->hasrealroots == 1 && (*nbr) > 0){ mpz_clear(tmp); return -1; } } else{//1 est racine //BUG Ici il faut diviser P par x-1 mpz_add_ui(tmp, tmp, 1); merge_root(roots, tmp, k+1, 1, 0, *nbr, flags->bound_pos, flags->bound_neg, flags->sign); (*nbr) ++; if(flags->verbose>=1){ fprintf(stderr,"+"); if((*nbr) % 100 == 0) fprintf(stderr, "[%lu]",(*nbr)); } if(flags->hasrealroots==1 && (*nbr)>0){ mpz_clear(tmp); return -1; } } /* if(flags->debug==1){ */ /* long bo=mpz_sgn(upoly[0]); */ /* long to=mpz_poly_sign_at_one(upol, (*deg), flags->Values); */ /* fprintf(stderr,"[d:%ld, %ld, %ld]",bo,shalf,to); */ /* } */ mpz_clear(tmp); return k; } static long nb_default_case_in_bisection_rec(mpz_t *upol, unsigned long int *deg, mpz_t c, const long k, mpz_t tmp, interval *roots, unsigned long int *nbr, usolve_flags *flags, int is_half_root, mpz_t tmp_half){ long oldk, nb; double e_time; mpz_set(tmp, c); int branch_left = 1; int branch_right = 1; if(flags->verbose>=1){ fprintf(stderr,"-"); } mpz_mul_2exp(tmp, tmp, 1); USOLVEmpz_poly_rescale_normalize_2exp_th(upol, -1, *deg, flags->nthreads); if(branch_left==1){ oldk = bisection_rec(upol, deg, tmp, k+1, roots, nbr, flags, tmp_half); } else{ if(flags->verbose >= 1) fprintf(stderr, "!"); oldk = k + 1; } if(flags->hasrealroots == 1 && (*nbr)>0){ mpz_clear(tmp); return -1; } mpz_add_ui(tmp, tmp, 1); if(is_half_root){ merge_root(roots, tmp, k + 1, 1, 0, *nbr, flags->bound_pos, flags->bound_neg, flags->sign); (*nbr)++; if(flags->verbose>=1){ fprintf(stderr,"+"); if((*nbr) % 100 == 0) fprintf(stderr, "[%lu]",(*nbr)); } if(flags->hasrealroots == 1 && (*nbr)>0){ mpz_clear(tmp); return -1; } } if (oldk == -1){ mpz_clear(tmp); return -1; } e_time = realtime(); if(flags->verbose>=1){ fprintf(stderr,"*"); } if(flags->classical_algo==1){ taylorshift1_naive(upol, *deg); } else{ taylorshift1_dac(upol, *deg, flags->tmpol, flags->shift_pwx, flags->pwx, flags->nthreads); } flags->time_shift += (realtime()-e_time); (flags->transl)++; if (oldk > k + 1){ USOLVEmpz_poly_rescale_normalize_2exp_th(upol, oldk - (k + 1), *deg, flags->nthreads); } if(branch_right==1){ oldk = bisection_rec(upol, deg, tmp, k+1, roots, nbr, flags, tmp_half); } else{ oldk = k + 1; nb = mpz_poly_sgn_variations_coeffs_is_zero(upol, (*deg)); if(flags->verbose >= 1) fprintf(stderr, "!"); if(nb == 0) oldk = -1; } if (oldk == -1){ mpz_clear(tmp); return -1; } if(flags->hasrealroots==1 && (*nbr)>0){ mpz_clear(tmp); return -1; } mpz_clear(tmp); return oldk; } /* investigates (c / 2^k, (c+1) / 2^k) */ /* returns k */ static long bisection_rec(mpz_t *upol, unsigned long *deg, mpz_t c, long k, interval *roots, unsigned long int *nbr, usolve_flags *flags, mpz_t tmp_half){ /* display_roots_system(stderr, roots, *nbr); */ long nb; long shalf; long bsgn = 0; mpz_t tmp; double e_time; mpz_init(tmp); (flags->node_looked)++; if(flags->verbose == 4){ fprintf(stderr,"["); mpz_out_str(stderr, 10, c); fprintf(stderr,",%lu]", k); } if(flags->verbose >= 5){ fprintf(stderr,"["); mpz_out_str(stderr, 10, c); fprintf(stderr,",%lu][bs=%lu]", k, mpz_poly_max_bsize_coeffs(upol, *deg)); } is_zero_root(upol, c, k, deg, roots, nbr, flags); unsigned int olddeg = *deg; if(flags->hasrealroots == 1 && (*nbr)>0){ return -1; } /* if 1 / 2 is a root, upol is divided by (x-1/2) */ /* shalf takes the sign of the new obtained poly at 1/2 */ shalf = manage_root_at_one_half(upol, c, k, deg, tmp_half, nbr, flags); if(flags->hasrealroots == 1 && (*nbr)>0){ mpz_clear(tmp); return -1; } int is_half_root = 0; if(olddeg != *deg){ is_half_root = 1; } nb = mpz_poly_sgn_variations_coeffs_is_zero(upol, (*deg)); if(nb == 0){ if(is_half_root){ mpz_set(tmp, c); mpz_mul_2exp(tmp, tmp, 1); mpz_add_ui(tmp, tmp, 1); merge_root(roots, tmp, k+1, 1, 0, *nbr, flags->bound_pos, flags->bound_neg, flags->sign); (*nbr)++; if(flags->verbose>=1){ fprintf(stderr,"+"); if((*nbr) % 100 == 0) fprintf(stderr, "[%lu]",(*nbr)); } if(flags->hasrealroots==1 && (*nbr)>0){ mpz_clear(tmp); return -1; } } if(flags->verbose>=1){ fprintf(stderr,"!"); } mpz_clear(tmp); return -1; } if(flags->verbose>=2){ fprintf(stderr,"c"); } e_time = realtime(); if(flags->classical_algo==1){ nb = descartes_classical(upol, flags->tmpol_desc, *deg, shalf, &bsgn); } else{ nb = descartes(upol, flags->tmpol_desc, *deg, shalf, &bsgn, flags); } flags->time_desc += (realtime()-e_time); if(flags->verbose>=3){ fprintf(stderr,"[nb=%lu]",nb); } if (bsgn == -1){ mpz_clear(tmp); return -1; } long bot = mpz_sgn(upol[0]); long top = mpz_poly_sign_at_one(upol, (*deg), flags->Values); switch (nb){ case 0: /* no root */ return nb_0_case_in_bisection_rec(c, k, tmp, roots, nbr, flags, is_half_root); case 1: /* one root exactly */ return nb_1_case_in_bisection_rec(c, k, tmp, roots, nbr, flags, is_half_root, bot, top, shalf); case 2: if ((bsgn && (flags->classical_algo)==1) || (flags->classical_algo == 0 && bot * shalf<0 && top * shalf<=0)){ return nb_2_case_in_bisection_rec(c, k, tmp, roots, nbr, flags, is_half_root, bot, top, shalf); } default: /* recursive call on each half of the interval */ return nb_default_case_in_bisection_rec(upol, deg, c, k, tmp, roots, nbr, flags, is_half_root, tmp_half); } } static void initialize_flags(usolve_flags *flags){ flags->search = 0; flags->prec_isole = 16; flags->precision_loss = 0; flags->bound_pos = 0; flags->bound_neg = 0; flags->sign = 0; flags->revert = 1; flags->hasrealroots = 0; flags->transl = 0; flags->node_looked = 0; flags->half_done = 0; flags->cur_deg = 0; flags->pwx = 0; flags->nblocks = 0; flags->npwr = 0; flags->shift_pwx = NULL; flags->tmpol = NULL; flags->tmpol_desc = NULL; flags->Values = NULL; flags->tmp_threads = NULL; flags->pols_threads = NULL; flags->time_desc = 0; flags->time_shift = 0; flags->nthreads = 1; flags->verbose = 0; flags->bfile = 0; flags->classical_algo = 0; flags->print_stats = 0; flags->debug = 0; } static void initialize_heap_flags(usolve_flags *flags, const unsigned long int deg){ if(flags->classical_algo==0){ flags->cur_deg = deg; flags->pwx = compute_degpower(flags->cur_deg); if(flags->pwx>=flags->cur_deg){ flags->nblocks = 0; flags->npwr=0; } else{ flags->nblocks = 1<pwx); flags->npwr=LOG2(flags->nblocks); } if(flags->npwr>0){ flags->shift_pwx=(mpz_t **)malloc(sizeof(mpz_t *)*(flags->npwr)); allocate_shift_pwx(flags->shift_pwx, flags->npwr, flags->pwx); compute_shift_pwx(flags->shift_pwx, flags->cur_deg, flags->npwr, flags->pwx, flags->nthreads); } else{ flags->shift_pwx = NULL; } flags->tmpol = (mpz_t *)(malloc(sizeof(mpz_t)*(deg+1))); for(int i=0; i<=deg; i++){ mpz_init(flags->tmpol[i]); } flags->tmpol_desc = (mpz_t *)(malloc(sizeof(mpz_t)*(deg+1))); for(int i=0; i<=deg; i++){ mpz_init(flags->tmpol_desc[i]); } if(flags->nthreads>=1 && 0==1){ /* used for parallel Taylor shift */ flags->tmp_threads = malloc(sizeof(mpz_t *) * (flags->nthreads + 1)); flags->pols_threads = malloc(sizeof(mpz_t *) * flags->nthreads); mpz_t ** tmp = flags->tmp_threads; mpz_t ** pols = flags->pols_threads; for(int i = 0; i <= flags->nthreads; i++){ tmp[i] = (mpz_t *)malloc((deg + 1) * sizeof(mpz_t)); for(unsigned long int j = 0; j <= deg; j++){ mpz_init2(tmp[i][j], 2 * deg); } } for(int i = 0; i < flags->nthreads; i++){ pols[i] = (mpz_t *)malloc((deg + 1) * sizeof(mpz_t)); for(unsigned long int j = 0; j <= deg; j++){ mpz_init2(pols[i][j], 2 * deg); } } } } flags->Values = malloc(sizeof(mpz_t) * 2); mpz_init(flags->Values[0]); mpz_init(flags->Values[1]); } /* warning: does not free flags->shift_pwx */ static inline void free_heap_flags(usolve_flags *flags, const unsigned long int deg){ if(flags->classical_algo == 0){ for(unsigned long int i = 0; i <= deg; i++){ mpz_clear(flags->tmpol_desc[i]); mpz_clear(flags->tmpol[i]); } mpz_clear(flags->Values[0]); mpz_clear(flags->Values[1]); free(flags->Values); if(flags->nthreads>=1 &&0==1){ for(int i = 0; i < flags->nthreads; i++){ for(unsigned long int j = 0; j <= deg; j++){ mpz_clear(flags->tmp_threads[i][j]); mpz_clear(flags->pols_threads[i][j]); } free(flags->tmp_threads[i]); free(flags->pols_threads[i]); } free(flags->tmp_threads); free(flags->pols_threads); } } } static void display_stats(usolve_flags *flags){ fprintf(stderr,"\n"); fprintf(stderr,"Number of nodes : %lu\n", flags->node_looked); fprintf(stderr,"Number of shifts : %lu\n", flags->transl); fprintf(stderr,"Number of half splits : %lu\n", flags->half_done); fprintf(stderr,"Time in Descartes (elapsed): %.2f sec\n", flags->time_desc); fprintf(stderr,"Time in Taylor shifts (elapsed): %.2f sec\n", flags->time_shift); fprintf(stderr,"\n"); } /* warning: does not check that upol is square-free (should be done outside) */ interval *bisection_Uspensky(mpz_t *upol0, unsigned long deg, unsigned long int *nb_pos_roots, unsigned long int *nb_neg_roots, usolve_flags *flags){ interval *pos_roots = (interval *)malloc(deg * sizeof(interval)); interval *neg_roots = (interval *)malloc(deg * sizeof(interval)); unsigned int nb_positive_roots = 0, nb_negative_roots = 0; mpz_t tmp_half; mpz_init(tmp_half); unsigned long deg0 = deg; mpz_t e; mpz_init_set_ui(e, 0); *nb_pos_roots = 0; *nb_neg_roots = 0; int zero_root = 0; if(mpz_sgn(upol0[0]) == 0){ merge_root(pos_roots, e, 0, 1, 0, *nb_pos_roots, 0, 0, 1); (*nb_pos_roots) ++; nb_positive_roots++; zero_root = 1; } if(mpz_sgn(upol0[0]) == 0 && mpz_sgn(upol0[1])==0){ fprintf(stderr, "0 is a multiple root ; the input polynomial must be square-free\n"); free(pos_roots); free(neg_roots); mpz_clear(e); mpz_clear(tmp_half); exit(1); } if(zero_root==0){ deg = deg0; } else{ deg = (deg0 - 1); } mpz_t *upol = (mpz_t *) malloc ((deg + 1) * sizeof(mpz_t)); if(zero_root == 0){ for (long i = 0; i <= deg; i++){ mpz_init_set(upol[i], upol0[i]); } } else{ for (long i = 0; i <= deg; i++){ mpz_init_set(upol[i], upol0[1 + i]); } } if(flags->search >= 0 && deg > 0){ flags->sign = 0; flags->bound_pos = bound_roots(upol, deg); if(flags->verbose>=1){ fprintf(stderr, "Bound for positive roots: %ld\n\n", flags->bound_pos); } USOLVEmpz_poly_rescale_normalize_2exp_th(upol, flags->bound_pos, deg, flags->nthreads); initialize_heap_flags(flags, deg); unsigned olddeg = deg; bisection_rec(upol, °, e, 0, pos_roots, nb_pos_roots, flags, tmp_half); nb_positive_roots = *nb_pos_roots; free_heap_flags(flags, olddeg); unallocate_shift_pwx(flags->shift_pwx, flags->npwr, flags->pwx); } /* replaces upol(x) by upol(-x) => negative roots */ if(zero_root == 0){ deg = deg0; } else{ deg = (deg0 - 1); } if(zero_root==0){ for(long i = 0; i <= deg; i++){ if (i % 2 == 1){ mpz_neg(upol[i], upol0[i]); } else{ mpz_set(upol[i], upol0[i]); } } } else{ for(long i = 0; i <= deg; i++) { if (i % 2 == 1){ mpz_neg(upol[i], upol0[i + 1]); } else{ mpz_set(upol[i], upol0[i + 1]); } } } if(flags->search<=0 && deg > 0){ flags->bound_neg = bound_roots(upol, deg); USOLVEmpz_poly_rescale_normalize_2exp_th(upol, flags->bound_neg, deg, flags->nthreads); if(flags->verbose>=1){ fprintf(stderr, "\nBound for negative roots: %ld\n\n", flags->bound_neg); } mpz_set_ui(e, 0); flags->sign = 1; initialize_heap_flags(flags, deg); unsigned long int olddeg = deg; bisection_rec(upol, °, e, 0, neg_roots, nb_neg_roots, flags, tmp_half); nb_negative_roots = (*nb_neg_roots); free_heap_flags(flags, olddeg); unallocate_shift_pwx(flags->shift_pwx, flags->npwr, flags->pwx); } unsigned long int nbroots = nb_positive_roots + nb_negative_roots; interval *roots = (interval *)malloc(nbroots * sizeof(interval)); for(unsigned int k = 0; k < nb_negative_roots; k++){ roots[k] = neg_roots[nb_negative_roots - 1 -k]; } for(unsigned int k = nb_negative_roots; k < nbroots; k++){ roots[k] = pos_roots[k-nb_negative_roots]; } /* needs to assign signs since this info may have been corrupted */ /* (because of exact roots) */ int b = mpz_sgn(upol0[deg0]); if(deg0 % 2 == 1){ b = -b; } if(nbroots>0){ assign_sign_left(roots, nb_negative_roots, nb_positive_roots, b); } if(zero_root == 0){ deg = deg0; } else{ deg = (deg0 - 1); } for(long i = 0; i <= deg; i++){ mpz_clear(upol[i]); } free(upol); free(pos_roots); free(neg_roots); mpz_clear(e); mpz_clear(tmp_half); return roots; } interval *real_roots(mpz_t *upoly, unsigned long deg, unsigned long int *nb_pos_roots, unsigned long int *nb_neg_roots, const int32_t precision, int nthrds, int info_level){ usolve_flags *flags = (usolve_flags*)(malloc(sizeof(usolve_flags))); initialize_flags(flags); flags->cur_deg = deg; flags->prec_isole = precision; if(info_level){ fprintf(stderr, "Real root isolation starts at precision %d\n", precision); } if (info_level > 0) { flags->verbose = info_level - 1; } else { flags->verbose = 0; } if(info_level>1){ flags->print_stats = 1; } flags->nthreads = nthrds; if(flags->verbose>=1 || flags->print_stats == 1){ fprintf(stderr, "Degree = %ld \t Max bit size = %lu Min bit size = %lu \n", flags->cur_deg, mpz_poly_max_bsize_coeffs(upoly, deg), mpz_poly_min_bsize_coeffs(upoly, deg)); fprintf(stderr, "nthreads = %d\n", flags->nthreads); } double e_time = realtime ( ); interval *roots = bisection_Uspensky(upoly, deg, nb_pos_roots, nb_neg_roots, flags); unsigned long int nbroots = *nb_pos_roots + *nb_neg_roots; for(unsigned long int i = 0; i < nbroots; i++){ if(roots[i].isexact){ if(roots[i].k < 0){ roots[i].k = 0; } } } /* display_roots_system(stderr, roots, nbroots); */ /* fprintf(stderr, "First root \n"); */ /* display_root(stderr, roots); */ e_time = realtime ( ) - e_time; if(flags->verbose>=1){ fprintf(stderr, "\n"); } if((flags->verbose>=1) || (flags->print_stats>=1)){ fprintf(stderr,"Time for isolation (elapsed): %.2f sec\n", e_time); } double refine_time = realtime(); double step = (e_time+1) / (deg) * 1000 * LOG2(flags->prec_isole) * 2; if(nbroots > 0 && flags->prec_isole >= 0){ if(flags->classical_algo > 0){ refine_all_roots_naive(upoly,deg, roots, nbroots, flags->prec_isole, flags->classical_algo, flags->debug); } else{ refine_QIR_roots_adaptative(upoly, °, roots, *nb_neg_roots, *nb_pos_roots, flags->prec_isole, flags->verbose, step, flags->nthreads); } } refine_time = realtime() - refine_time; for(unsigned long int i = 0; i < nbroots; i++){ if(roots[i].isexact){ if(roots[i].k < 0){ roots[i].k = 0; } } } if(flags->print_stats>=1){ display_stats(flags); } if((flags->verbose>=1) || (flags->print_stats>=1)){ fprintf(stderr,"Time for isolation (elapsed): %.2f sec\n", e_time); fprintf(stderr,"Time for refinement (elapsed): %.2f sec\n", refine_time); } free(flags); return roots; } msolve-0.6.5/src/usolve/utils.c000066400000000000000000000164401456710632100164510ustar00rootroot00000000000000/* This file is part of msolve. * * msolve 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. * * msolve 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 msolve. If not, see * * Authors: * Jérémy Berthomieu * Christian Eder * Mohab Safey El Din */ #include #include #include #include #include #define bit_one_index(x) mpz_scan1((x), 0) #ifdef USEFLINT #include "flint/flint.h" #include "flint/fmpz.h" #include "flint/fmpz_poly.h" #endif #ifndef USOLVE #define USOLVE #endif unsigned long int mpz_poly_max_bsize_coeffs(mpz_t *upol, long int deg){ if(deg<0) return -1; unsigned long int max = 0, bs; for(int i=0 ; i<=deg; i++){ bs = ilog2_mpz(upol[i]); if(bs>max){ max = bs; } } return max; } /* returns c s.t. 2^c divides the content of upol */ static unsigned long int mpz_poly_remove_binary_content(mpz_t *upol, unsigned long deg) { unsigned long int c, i, nbit; i = 0; if(mpz_sgn(upol[deg])==0){ return 0; } while (mpz_sgn(upol[i]) == 0) i++; c = bit_one_index(upol[i]); for( ; (i <= deg) && c; i++){ if (mpz_sgn(upol[i]) != 0) { nbit = bit_one_index(upol[i]); if (nbit < c) c = nbit; } } if (c == 0) return 0; for (i = 0; i <= deg; i++){ mpz_fdiv_q_2exp(upol[i], upol[i], c); } return c; } static inline void USOLVEmpz_get_content(mpz_t *upol, unsigned long int deg, mpz_t *g){ if(deg>=1){ mpz_set(g[0], upol[0]); for(unsigned long int i = 1; i <= deg; i++){ mpz_gcd(g[0], g[0], upol[i]); if(mpz_cmp_ui(g[0], 1)==0){ return; } } } } static inline void USOLVEmpz_remove_content(mpz_t *upol, unsigned long int deg, mpz_t *g){ for(unsigned long int i = 0; i <= deg; i++){ mpz_divexact(upol[i], upol[i], g[0]); } } static inline void USOLVEmpz_restore_content(mpz_t *upol, unsigned long int deg, mpz_t *g){ for(unsigned long int i = 0; i <= deg; i++){ mpz_mul(upol[i], upol[i], g[0]); } } /* computed the numerator of the quotient of the division of upol by (x-c/2^k) */ static void USOLVEnumer_quotient(mpz_t *upol, unsigned long int *deg, mpz_t c, unsigned long int k){ for(unsigned long int i = 0; i <= *deg; i++){ mpz_mul_2exp(upol[i], upol[i], (*deg - 1) * k ); } mpz_t tmp; mpz_init(tmp); for(long int i = *deg-1; i >=1; i--){ mpz_div_2exp(tmp, upol[i+1], k); mpz_mul(tmp, tmp, c); mpz_add(upol[i], upol[i], tmp); } for(long int i = 0 ; i <= *deg - 1; i++){ mpz_set(upol[i], upol[i+1]); } mpz_poly_remove_binary_content(upol, *deg - 1); *deg = *deg - 1; mpz_clear(tmp); } /* prints coefficients of pol in increasing degree order */ static inline void USOLVEmpz_poly_print(mpz_t *upol, unsigned long int deg){ int i; for(i=0;i<=deg;i++){ gmp_printf("%Zd", upol[i]); fprintf(stdout," "); } fprintf(stdout, "\n"); } /* prints coefficients of pol in decreasing degree order */ static inline void USOLVEmpz_poly_print_maple(mpz_t *upol, unsigned long int deg){ int i; for(i=deg;i>=1;i--){ gmp_printf("(%Zd)", upol[i]); fprintf(stdout,"*x^%d+",i); } gmp_printf("(%Zd)", upol[0]); fprintf(stdout, ";\n"); } /* From the polynomial upol, of degree deg, and b>=0, computes (inplace) - when b>0 upoly(X*2^b), remove its content c, and return the content c. - when b<=0 numer(upoly(X*2^b)), remove its content c, and return the content c. */ static inline int USOLVEmpz_poly_rescale_normalize_2exp_th(mpz_t *upol, long int b, unsigned long deg, unsigned int nthreads){ long int i; if (b > 0) { // j = b; #ifdef _OPENMP omp_set_num_threads(nthreads); #endif #pragma omp parallel for num_threads(nthreads) for(i = 1; i <= deg; i++){ mpz_mul_2exp(upol[i], upol[i], i*b); } } else{ #ifdef _OPENMP omp_set_num_threads(nthreads); #endif #pragma omp parallel for num_threads(nthreads) for(i=0; i=0, computes (inplace) - when b>0 upoly(X*c*2^b), remove its content, and return the content. - when b<=0 numer(upoly(X*c*2^b)), remove its content, and return the content. */ static inline int USOLVEmpz_poly_rescale_normalize_2exp_th_long(mpz_t *upol, unsigned long deg, long int b, long int c, unsigned int nthreads){ long int i; mpz_t coef;mpz_init(coef);mpz_set_si(coef, c); if (b > 0) { #ifdef _OPENMP omp_set_num_threads(nthreads); #endif #pragma omp parallel for num_threads(nthreads) for(i = 1; i <= deg; i++){ mpz_mul(upol[i], upol[i], coef); mpz_mul_2exp(upol[i], upol[i], i*b); mpz_mul_si(coef, coef, c); } } else{ #ifdef _OPENMP omp_set_num_threads(nthreads); #endif #pragma omp parallel for num_threads(nthreads) for(i=0; i= 0; i--){ bs = ilog2_mpz(upol[i]); if(bs 0; i--){ int c = mpz_cmp_ui(upol[i],0); long int l = ilog2_mpz(upol[i]); N = min((bsize - i + 1) * L + 1, min(deg, (i + 1)*L + 1)); if(l <= N || c==0){ boo = 0; } if( mpz_sgn(upol[i]) * s < 0 && l > N && c!=0){ nb = nb + 1; s = mpz_sgn(upol[i]); if(nb >= 3){ return nb; } } } N = L + 1; int c = mpz_cmp_ui(upol[0],0); long int l = ilog2_mpz(upol[0]); if(l <= N || c==0){ boo = 0; } if(s*mpz_sgn(upol[0]) < 0 && l> N && c!=0){ nb = nb + 1; } if(nb>=3 || boo == 1){ return nb; } return -1; } msolve-0.6.5/test/000077500000000000000000000000001456710632100140135ustar00rootroot00000000000000msolve-0.6.5/test/diff/000077500000000000000000000000001456710632100147235ustar00rootroot00000000000000msolve-0.6.5/test/diff/diff_F4SAT-31.sh000077500000000000000000000015771456710632100173260ustar00rootroot00000000000000#!/bin/bash file=F4SAT-31 $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -S -g 2 -l 2 -t 1 if [ $? -gt 0 ]; then exit 1 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 2 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -S -g 2 -l 2 -t 2 if [ $? -gt 0 ]; then exit 21 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 22 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -S -g 2 -l 44 -t 1 if [ $? -gt 0 ]; then exit 41 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 42 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -S -g 2 -l 44 -t 2 if [ $? -gt 0 ]; then exit 61 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 62 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_F4SAT-byone-31.sh000077500000000000000000000016051456710632100204300ustar00rootroot00000000000000#!/bin/bash file=F4SAT-byone-31 $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -S -g 2 -l 2 -t 1 if [ $? -gt 0 ]; then exit 1 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 2 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -S -g 2 -l 2 -t 2 if [ $? -gt 0 ]; then exit 21 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 22 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -S -g 2 -l 44 -t 1 if [ $? -gt 0 ]; then exit 41 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 42 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -S -g 2 -l 44 -t 2 if [ $? -gt 0 ]; then exit 61 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 62 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_bug_2nd_prime_bad.sh000077500000000000000000000015741456710632100216030ustar00rootroot00000000000000#!/bin/bash file=bug-2nd-prime-bad $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -g 2 -l 2 -t 1 if [ $? -gt 0 ]; then exit 1 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 2 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -g 2 -l 2 -t 2 if [ $? -gt 0 ]; then exit 21 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 22 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -g 2 -l 44 -t 1 if [ $? -gt 0 ]; then exit 41 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 42 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -g 2 -l 44 -t 2 if [ $? -gt 0 ]; then exit 61 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 62 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_bug_68.sh000077500000000000000000000015351456710632100173500ustar00rootroot00000000000000#!/bin/bash file=bug_68 $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 2 -t 1 if [ $? -gt 0 ]; then exit 1 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 2 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 2 -t 2 if [ $? -gt 0 ]; then exit 21 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 22 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 44 -t 1 if [ $? -gt 0 ]; then exit 41 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 42 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 44 -t 2 if [ $? -gt 0 ]; then exit 61 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 62 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_bug_empty_tracer.sh000077500000000000000000000015731456710632100216130ustar00rootroot00000000000000#!/bin/bash file=bug-empty-tracer $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -g 2 -l 2 -t 1 if [ $? -gt 0 ]; then exit 1 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 2 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -g 2 -l 2 -t 2 if [ $? -gt 0 ]; then exit 21 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 22 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -g 2 -l 44 -t 1 if [ $? -gt 0 ]; then exit 41 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 42 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -g 2 -l 44 -t 2 if [ $? -gt 0 ]; then exit 61 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 62 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_cp_d_3_n_4_p_2.sh000077500000000000000000000001021456710632100206720ustar00rootroot00000000000000#!/bin/bash file=cp_d_3_n_4_p_2 source test/diff/diff_source.sh msolve-0.6.5/test/diff/diff_eco11-31.sh000077500000000000000000000000741456710632100174040ustar00rootroot00000000000000#!/bin/bash file=eco11-31 source test/diff/diff_source.sh msolve-0.6.5/test/diff/diff_elim-31.sh000077500000000000000000000033461456710632100174270ustar00rootroot00000000000000#!/bin/bash file=elim-31 $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -e 1 -g 2 -l 2 -t 1 if [ $? -gt 0 ]; then exit 1 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 2 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -e 2 -g 2 -l 2 -t 1 if [ $? -gt 0 ]; then exit 3 fi diff test/diff/$file.res output_files/$file.e2.res if [ $? -gt 0 ]; then exit 4 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -e 1 -g 2 -l 2 -t 2 if [ $? -gt 0 ]; then exit 21 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 22 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -e 2 -g 2 -l 2 -t 2 if [ $? -gt 0 ]; then exit 23 fi diff test/diff/$file.res output_files/$file.e2.res if [ $? -gt 0 ]; then exit 24 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -e 1 -g 2 -l 44 -t 1 if [ $? -gt 0 ]; then exit 41 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 42 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -e 2 -g 2 -l 44 -t 1 if [ $? -gt 0 ]; then exit 43 fi diff test/diff/$file.res output_files/$file.e2.res if [ $? -gt 0 ]; then exit 44 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -e 1 -g 2 -l 44 -t 2 if [ $? -gt 0 ]; then exit 61 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 62 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -e 2 -g 2 -l 44 -t 2 if [ $? -gt 0 ]; then exit 63 fi diff test/diff/$file.res output_files/$file.e2.res if [ $? -gt 0 ]; then exit 64 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_elim-qq.sh000077500000000000000000000033461456710632100176250ustar00rootroot00000000000000#!/bin/bash file=elim-qq $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -e 1 -g 2 -l 2 -t 1 if [ $? -gt 0 ]; then exit 1 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 2 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -e 2 -g 2 -l 2 -t 1 if [ $? -gt 0 ]; then exit 3 fi diff test/diff/$file.res output_files/$file.e2.res if [ $? -gt 0 ]; then exit 4 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -e 1 -g 2 -l 2 -t 2 if [ $? -gt 0 ]; then exit 21 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 22 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -e 2 -g 2 -l 2 -t 2 if [ $? -gt 0 ]; then exit 23 fi diff test/diff/$file.res output_files/$file.e2.res if [ $? -gt 0 ]; then exit 24 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -e 1 -g 2 -l 44 -t 1 if [ $? -gt 0 ]; then exit 41 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 42 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -e 2 -g 2 -l 44 -t 1 if [ $? -gt 0 ]; then exit 43 fi diff test/diff/$file.res output_files/$file.e2.res if [ $? -gt 0 ]; then exit 44 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -e 1 -g 2 -l 44 -t 2 if [ $? -gt 0 ]; then exit 61 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 62 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -e 2 -g 2 -l 44 -t 2 if [ $? -gt 0 ]; then exit 63 fi diff test/diff/$file.res output_files/$file.e2.res if [ $? -gt 0 ]; then exit 64 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_input-overflow-16.sh000077500000000000000000000015511456710632100215000ustar00rootroot00000000000000#!/bin/bash file=input-overflow-16 $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 2 -t 1 if [ $? -gt 0 ]; then exit 1 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 2 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 2 -t 2 if [ $? -gt 0 ]; then exit 21 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 22 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 44 -t 1 if [ $? -gt 0 ]; then exit 41 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 42 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 44 -t 2 if [ $? -gt 0 ]; then exit 61 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 62 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_kat6-31.sh000077500000000000000000000000731456710632100173400ustar00rootroot00000000000000#!/bin/bash file=kat6-31 source test/diff/diff_source.sh msolve-0.6.5/test/diff/diff_kat7-qq.sh000077500000000000000000000000731456710632100175370ustar00rootroot00000000000000#!/bin/bash file=kat7-qq source test/diff/diff_source.sh msolve-0.6.5/test/diff/diff_mq_2_1.sh000077500000000000000000000015351456710632100173340ustar00rootroot00000000000000#!/bin/bash file=mq_2_1 $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 2 -t 1 if [ $? -gt 0 ]; then exit 1 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 2 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 2 -t 2 if [ $? -gt 0 ]; then exit 21 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 22 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 44 -t 1 if [ $? -gt 0 ]; then exit 41 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 42 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 44 -t 2 if [ $? -gt 0 ]; then exit 61 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 62 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_multy-16.sh000077500000000000000000000000741456710632100176510ustar00rootroot00000000000000#!/bin/bash file=multy-16 source test/diff/diff_source.sh msolve-0.6.5/test/diff/diff_multy-31.sh000077500000000000000000000000741456710632100176460ustar00rootroot00000000000000#!/bin/bash file=multy-31 source test/diff/diff_source.sh msolve-0.6.5/test/diff/diff_multy-qq.sh000077500000000000000000000000741456710632100200440ustar00rootroot00000000000000#!/bin/bash file=multy-qq source test/diff/diff_source.sh msolve-0.6.5/test/diff/diff_nf_16.sh000077500000000000000000000003631456710632100171650ustar00rootroot00000000000000#!/bin/bash file=nf-16 $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -n2 if [ $? -gt 0 ]; then exit 3 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 4 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_nf_31.sh000077500000000000000000000003631456710632100171620ustar00rootroot00000000000000#!/bin/bash file=nf-31 $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -n2 if [ $? -gt 0 ]; then exit 1 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 2 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_nf_8.sh000077500000000000000000000003621456710632100171050ustar00rootroot00000000000000#!/bin/bash file=nf-8 $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -n2 if [ $? -gt 0 ]; then exit 5 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 6 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_nf_lm_bug.sh000077500000000000000000000003671456710632100202100ustar00rootroot00000000000000#!/bin/bash file=nf-lm-bug $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -n3 if [ $? -gt 0 ]; then exit 5 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 6 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_nonradical_radicalshape-31.sh000077500000000000000000000001161456710632100233030ustar00rootroot00000000000000#!/bin/bash file=nonradical_radicalshape-31 source test/diff/diff_source.sh msolve-0.6.5/test/diff/diff_nonradical_radicalshape-no-square-31.sh000077500000000000000000000017261456710632100252230ustar00rootroot00000000000000#!/bin/bash file=nonradical_radicalshape-no-square-31 # source test/diff/diff_source.sh $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -P 2 -l 2 -t 1 -c 0 if [ $? -gt 0 ]; then exit 3 fi diff test/diff/$file.res output_files/$file.c0.res if [ $? -gt 0 ]; then exit 4 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -P 2 -l 2 -t 2 -c 0 if [ $? -gt 0 ]; then exit 23 fi diff test/diff/$file.res output_files/$file.c0.res if [ $? -gt 0 ]; then exit 24 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -P 2 -l 44 -t 1 -c 0 if [ $? -gt 0 ]; then exit 43 fi diff test/diff/$file.res output_files/$file.c0.res if [ $? -gt 0 ]; then exit 44 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -P 2 -l 44 -t 2 -c 0 if [ $? -gt 0 ]; then exit 63 fi diff test/diff/$file.res output_files/$file.c0.res if [ $? -gt 0 ]; then exit 64 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_nonradical_radicalshape-no-square-qq.sh000077500000000000000000000027021456710632100254140ustar00rootroot00000000000000#!/bin/bash file=nonradical_radicalshape-no-square-qq # source test/diff/diff_source.sh $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 3 -l 2 -t 1 if [ $? -gt 0 ]; then exit 3 fi diff test/diff/$file.res output_files/$file.p3.res if [ $? -gt 0 ]; then exit 4 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -P 2 -l 2 -t 1 -c 0 if [ $? -ne 1 ]; then exit 5 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 3 -l 2 -t 2 if [ $? -gt 0 ]; then exit 23 fi diff test/diff/$file.res output_files/$file.p3.res if [ $? -gt 0 ]; then exit 24 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -P 2 -l 2 -t 2 -c 0 if [ $? -ne 1 ]; then exit 25 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 3 -l 44 -t 1 if [ $? -gt 0 ]; then exit 43 fi diff test/diff/$file.res output_files/$file.p3.res if [ $? -gt 0 ]; then exit 44 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -P 2 -l 44 -t 1 -c 0 if [ $? -ne 1 ]; then exit 45 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 3 -l 44 -t 2 if [ $? -gt 0 ]; then exit 63 fi diff test/diff/$file.res output_files/$file.p3.res if [ $? -gt 0 ]; then exit 64 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -P 2 -l 44 -t 2 -c 0 if [ $? -ne 1 ]; then exit 65 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_nonradical_radicalshape-qq.sh000077500000000000000000000016661456710632100235140ustar00rootroot00000000000000#!/bin/bash file=nonradical_radicalshape-qq source test/diff/diff_source.sh $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 3 -l 2 -t 1 if [ $? -gt 0 ]; then exit 3 fi diff test/diff/$file.res output_files/$file.p3.res if [ $? -gt 0 ]; then exit 4 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 3 -l 2 -t 2 if [ $? -gt 0 ]; then exit 23 fi diff test/diff/$file.res output_files/$file.p3.res if [ $? -gt 0 ]; then exit 24 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 3 -l 44 -t 1 if [ $? -gt 0 ]; then exit 43 fi diff test/diff/$file.res output_files/$file.p3.res if [ $? -gt 0 ]; then exit 44 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 3 -l 44 -t 2 if [ $? -gt 0 ]; then exit 63 fi diff test/diff/$file.res output_files/$file.p3.res if [ $? -gt 0 ]; then exit 64 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_nonradical_shape-31.sh000077500000000000000000000001071456710632100217630ustar00rootroot00000000000000#!/bin/bash file=nonradical_shape-31 source test/diff/diff_source.sh msolve-0.6.5/test/diff/diff_nonradical_shape-qq.sh000077500000000000000000000017071456710632100221700ustar00rootroot00000000000000#!/bin/bash file=nonradical_shape-qq source test/diff/diff_source.sh $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 1024 -l 2 -t 1 if [ $? -gt 0 ]; then exit 3 fi diff test/diff/$file.res output_files/$file.p1024.res if [ $? -gt 0 ]; then exit 4 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 1024 -l 2 -t 2 if [ $? -gt 0 ]; then exit 23 fi diff test/diff/$file.res output_files/$file.p1024.res if [ $? -gt 0 ]; then exit 24 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 1024 -l 44 -t 1 if [ $? -gt 0 ]; then exit 43 fi diff test/diff/$file.res output_files/$file.p1024.res if [ $? -gt 0 ]; then exit 44 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 1024 -l 44 -t 2 if [ $? -gt 0 ]; then exit 63 fi diff test/diff/$file.res output_files/$file.p1024.res if [ $? -gt 0 ]; then exit 64 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_one-16.sh000077500000000000000000000000741456710632100172600ustar00rootroot00000000000000#!/bin/bash file=one-16 source test/diff/diff_source.sh msolve-0.6.5/test/diff/diff_one-31.sh000077500000000000000000000000741456710632100172550ustar00rootroot00000000000000#!/bin/bash file=one-31 source test/diff/diff_source.sh msolve-0.6.5/test/diff/diff_one-qq.sh000077500000000000000000000016371456710632100174610ustar00rootroot00000000000000#!/bin/bash file=one-qq source test/diff/diff_source.sh $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -g 2 -l 2 -t 1 if [ $? -gt 0 ]; then exit 3 fi diff test/diff/$file.res output_files/$file.g2.res if [ $? -gt 0 ]; then exit 4 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -g 2 -l 2 -t 2 if [ $? -gt 0 ]; then exit 23 fi diff test/diff/$file.res output_files/$file.g2.res if [ $? -gt 0 ]; then exit 24 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -g 2 -l 44 -t 1 if [ $? -gt 0 ]; then exit 43 fi diff test/diff/$file.res output_files/$file.g2.res if [ $? -gt 0 ]; then exit 44 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -g 2 -l 44 -t 2 if [ $? -gt 0 ]; then exit 63 fi diff test/diff/$file.res output_files/$file.g2.res if [ $? -gt 0 ]; then exit 64 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_radical_shape-31.sh000077500000000000000000000001041456710632100212450ustar00rootroot00000000000000#!/bin/bash file=radical_shape-31 source test/diff/diff_source.sh msolve-0.6.5/test/diff/diff_radical_shape-qq.sh000077500000000000000000000001041456710632100214430ustar00rootroot00000000000000#!/bin/bash file=radical_shape-qq source test/diff/diff_source.sh msolve-0.6.5/test/diff/diff_reals_dim0-chgvar.sh000077500000000000000000000015411456710632100215420ustar00rootroot00000000000000#!/bin/bash file=bug-chgvar $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 2 -t 1 if [ $? -gt 0 ]; then exit 1 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 2 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 2 -t 2 if [ $? -gt 0 ]; then exit 21 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 22 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 44 -t 1 if [ $? -gt 0 ]; then exit 41 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 42 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 44 -t 2 if [ $? -gt 0 ]; then exit 61 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 62 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_reals_dim0-swapvar.sh000077500000000000000000000033051456710632100217530ustar00rootroot00000000000000#!/bin/bash file=reals_dim0-swapvar $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 2 -t 1 if [ $? -gt 0 ]; then exit 1 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 2 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 256 -l 2 -t 1 if [ $? -gt 0 ]; then exit 3 fi diff test/diff/$file.res output_files/$file.p256.res if [ $? -gt 0 ]; then exit 4 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 2 -t 2 if [ $? -gt 0 ]; then exit 21 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 22 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 256 -l 2 -t 2 if [ $? -gt 0 ]; then exit 23 fi diff test/diff/$file.res output_files/$file.p256.res if [ $? -gt 0 ]; then exit 24 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 44 -t 1 if [ $? -gt 0 ]; then exit 41 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 42 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 256 -l 44 -t 1 if [ $? -gt 0 ]; then exit 43 fi diff test/diff/$file.res output_files/$file.p256.res if [ $? -gt 0 ]; then exit 44 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 44 -t 2 if [ $? -gt 0 ]; then exit 61 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 62 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 256 -l 44 -t 2 if [ $? -gt 0 ]; then exit 63 fi diff test/diff/$file.res output_files/$file.p256.res if [ $? -gt 0 ]; then exit 64 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_reals_dim0.sh000077500000000000000000000032751456710632100203000ustar00rootroot00000000000000#!/bin/bash file=reals_dim0 $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 2 -t 1 if [ $? -gt 0 ]; then exit 1 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 2 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 256 -l 2 -t 1 if [ $? -gt 0 ]; then exit 3 fi diff test/diff/$file.res output_files/$file.p256.res if [ $? -gt 0 ]; then exit 4 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 2 -t 2 if [ $? -gt 0 ]; then exit 21 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 22 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 256 -l 2 -t 2 if [ $? -gt 0 ]; then exit 23 fi diff test/diff/$file.res output_files/$file.p256.res if [ $? -gt 0 ]; then exit 24 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 44 -t 1 if [ $? -gt 0 ]; then exit 41 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 42 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 256 -l 44 -t 1 if [ $? -gt 0 ]; then exit 43 fi diff test/diff/$file.res output_files/$file.p256.res if [ $? -gt 0 ]; then exit 44 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 44 -t 2 if [ $? -gt 0 ]; then exit 61 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 62 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 256 -l 44 -t 2 if [ $? -gt 0 ]; then exit 63 fi diff test/diff/$file.res output_files/$file.p256.res if [ $? -gt 0 ]; then exit 64 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_reals_extract.sh000077500000000000000000000033031456710632100211110ustar00rootroot00000000000000#!/bin/bash file=realroot-extract $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 2 -t 1 if [ $? -gt 0 ]; then exit 1 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 2 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 256 -l 2 -t 1 if [ $? -gt 0 ]; then exit 3 fi diff test/diff/$file.res output_files/$file.p256.res if [ $? -gt 0 ]; then exit 4 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 2 -t 2 if [ $? -gt 0 ]; then exit 21 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 22 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 256 -l 2 -t 2 if [ $? -gt 0 ]; then exit 23 fi diff test/diff/$file.res output_files/$file.p256.res if [ $? -gt 0 ]; then exit 24 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 44 -t 1 if [ $? -gt 0 ]; then exit 41 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 42 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 256 -l 44 -t 1 if [ $? -gt 0 ]; then exit 43 fi diff test/diff/$file.res output_files/$file.p256.res if [ $? -gt 0 ]; then exit 44 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -l 44 -t 2 if [ $? -gt 0 ]; then exit 61 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 62 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -p 256 -l 44 -t 2 if [ $? -gt 0 ]; then exit 63 fi diff test/diff/$file.res output_files/$file.p256.res if [ $? -gt 0 ]; then exit 64 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_source.sh000077500000000000000000000015441456710632100175560ustar00rootroot00000000000000#!/bin/bash $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -P 2 -l 2 -t 1 if [ $? -gt 0 ]; then exit 1 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 2 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -P 2 -l 2 -t 2 if [ $? -gt 0 ]; then exit 21 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 22 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -P 2 -l 44 -t 1 if [ $? -gt 0 ]; then exit 41 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 42 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -P 2 -l 44 -t 2 if [ $? -gt 0 ]; then exit 61 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 62 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_truncate_gb.sh000077500000000000000000000016171456710632100205540ustar00rootroot00000000000000#!/bin/bash file=kat8-qq-truncate $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -N 5 -g 2 -l 2 -t 1 if [ $? -gt 0 ]; then exit 1 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 2 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -N 5 -g 2 -l 2 -t 2 if [ $? -gt 0 ]; then exit 21 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 22 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -N 5 -g 2 -l 44 -t 1 if [ $? -gt 0 ]; then exit 41 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 42 fi $(pwd)/msolve -f input_files/$file.ms -o test/diff/$file.res \ -N 5 -g 2 -l 44 -t 2 if [ $? -gt 0 ]; then exit 61 fi diff test/diff/$file.res output_files/$file.res if [ $? -gt 0 ]; then exit 62 fi rm test/diff/$file.res msolve-0.6.5/test/diff/diff_xy-qq.sh000077500000000000000000000000711456710632100173270ustar00rootroot00000000000000#!/bin/bash file=xy-qq source test/diff/diff_source.sh msolve-0.6.5/test/fglm/000077500000000000000000000000001456710632100147405ustar00rootroot00000000000000msolve-0.6.5/test/fglm/build_matrixn_nonradical_radicalshape-31.c000066400000000000000000000100461456710632100250610ustar00rootroot00000000000000#include "../../src/msolve/libmsolve.c" int main(void) { int32_t la_option = 2; // by default int32_t use_signatures = 0; int32_t nr_threads = 1; int32_t info_level = 0; int32_t initial_hts = 17; int32_t max_pairs = 0; int32_t elim_block_len = 0; int32_t update_ht = 0; int32_t generate_pbm = 0; int32_t reduce_gb = 1; int32_t print_gb = 0; int32_t genericity_handling = 2; int32_t saturate = 0; int32_t colon = 0; int32_t normal_form = 0; int32_t normal_form_matrix = 0; int32_t is_gb = 0; int32_t get_param = 0; int32_t precision = 128; int32_t refine = 0; /* not used at the moment */ int32_t isolate = 0; /* not used at the moment */ files_gb *files = malloc(sizeof(files_gb)); files->in_file = "input_files/nonradical_radicalshape-31.ms"; files->out_file = NULL; FILE *fh = fopen(files->in_file, "r"); // int32_t mon_order = 0; int32_t nr_vars = 0; int32_t field_char = 9001; int32_t nr_gens = 0; data_gens_ff_t *gens = allocate_data_gens(); get_data_from_file(files->in_file, &nr_vars, &field_char,&nr_gens,gens); if (nr_vars != 2) return 101; if (field_char != 1073741827) return 102; if (nr_gens != 3) return 103; gens->rand_linear = 0; gens->random_linear_form = malloc(sizeof(int32_t)*(nr_vars)); param_t *param = NULL; mpz_param_t mpz_param; mpz_param_init(mpz_param); long nb_real_roots = 0; interval *real_roots = NULL; real_point_t *real_pts = NULL; param_t ** paramp = ¶m; mpz_param_t *mpz_paramp = &mpz_param; long *nb_real_roots_ptr = &nb_real_roots; interval **real_roots_ptr = &real_roots; real_point_t **real_pts_ptr = &real_pts; int32_t *bld = NULL; int32_t **blen = NULL; int32_t **bexp = NULL; void **bcf = NULL; int b = 0; /* counter for randomly chosen linear forms */ int round = -1; bld = malloc(sizeof(int32_t)); blen = malloc(sizeof(int32_t *)); bexp = malloc(sizeof(int32_t *)); bcf = malloc(sizeof(void *)); bs_t *bs = NULL; ht_t *bht = NULL; md_t *st = NULL; int error = 0; int success = 0; success = initialize_gba_input_data(&bs, &bht, &st,gens->lens, gens->exps, (void *)gens->cfs, 1073741827, 0 /* DRL order */,elim_block_len, gens->nvars,/* gens->field_char,0 [> DRL order <], gens->nvars, */ gens->ngens, saturate, initial_hts, nr_threads, max_pairs, update_ht, la_option, use_signatures, 1 /* reduce_gb */, 0, info_level); bs = core_gba(bs, st, &error, 1073741827); if (!success || error) { printf("Problem with F4, stopped computation.\n"); return 104; } export_results_from_gba(bld, blen, bexp,bcf, &malloc, &bs, &bht, &st); int32_t *bcf_ff = (int32_t *)(*bcf); int32_t *bexp_lm = get_lead_monomials(bld, blen, bexp, gens); long dquot = 0; int32_t *lmb= monomial_basis (bld[0], gens->nvars, bexp_lm,&dquot); sp_matfglm_t *matrix= build_matrixn(lmb, dquot, bld[0], blen, bexp, bcf_ff,bexp_lm, gens->nvars, gens->field_char); /* display_fglm_matrix (stdout, matrix); */ if (matrix->charac != field_char) return 105; if (matrix->ncols != 3) return 106; if (matrix->nrows != 2) return 107; if (matrix->dense_mat[0] != 0) return 201; if (matrix->dense_mat[1] != 0) return 202; if (matrix->dense_mat[2] != 0) return 203; if (matrix->dense_mat[3] != 0) return 204; if (matrix->dense_mat[4] != 0) return 205; if (matrix->dense_mat[5] != 0) return 206; if (matrix->triv_idx[0] != 0) return 207; if (matrix->triv_pos[0] != 1) return 208; if (matrix->dense_idx[0] != 1) return 209; if (matrix->dense_idx[1] != 2) return 210; if (matrix->dst[0] != 3) return 211; if (matrix->dst[1] != 3) return 212; return 0; } msolve-0.6.5/test/fglm/build_matrixn_nonradical_shape-31.c000066400000000000000000000200771456710632100235460ustar00rootroot00000000000000#include "../../src/msolve/libmsolve.c" int main(void) { int32_t la_option = 2; // by default int32_t use_signatures = 0; int32_t nr_threads = 1; int32_t info_level = 0; int32_t initial_hts = 17; int32_t max_pairs = 0; int32_t elim_block_len = 0; int32_t update_ht = 0; int32_t generate_pbm = 0; int32_t reduce_gb = 1; int32_t print_gb = 0; int32_t genericity_handling = 2; int32_t saturate = 0; int32_t colon = 0; int32_t normal_form = 0; int32_t normal_form_matrix = 0; int32_t is_gb = 0; int32_t get_param = 0; int32_t precision = 128; int32_t refine = 0; /* not used at the moment */ int32_t isolate = 0; /* not used at the moment */ files_gb *files = malloc(sizeof(files_gb)); files->in_file = "input_files/nonradical_shape-31.ms"; files->out_file = NULL; FILE *fh = fopen(files->in_file, "r"); // int32_t mon_order = 0; int32_t nr_vars = 0; int32_t field_char = 9001; int32_t nr_gens = 0; data_gens_ff_t *gens = allocate_data_gens(); get_data_from_file(files->in_file, &nr_vars, &field_char,&nr_gens,gens); if (nr_vars != 4) return 101; if (field_char != 1073741831) return 102; if (nr_gens != 4) return 103; gens->rand_linear = 0; gens->random_linear_form = malloc(sizeof(int32_t)*(nr_vars)); param_t *param = NULL; mpz_param_t mpz_param; mpz_param_init(mpz_param); long nb_real_roots = 0; interval *real_roots = NULL; real_point_t *real_pts = NULL; param_t ** paramp = ¶m; mpz_param_t *mpz_paramp = &mpz_param; long *nb_real_roots_ptr = &nb_real_roots; interval **real_roots_ptr = &real_roots; real_point_t **real_pts_ptr = &real_pts; int32_t *bld = NULL; int32_t **blen = NULL; int32_t **bexp = NULL; void **bcf = NULL; int b = 0; /* counter for randomly chosen linear forms */ int round = -1; bld = malloc(sizeof(int32_t)); blen = malloc(sizeof(int32_t *)); bexp = malloc(sizeof(int32_t *)); bcf = malloc(sizeof(void *)); bs_t *bs = NULL; ht_t *bht = NULL; md_t *st = NULL; int error = 0; int success = 0; success = initialize_gba_input_data(&bs, &bht, &st,gens->lens, gens->exps, (void *)gens->cfs, 1073741831, 0 /* DRL order */,elim_block_len, gens->nvars,/* gens->field_char,0 [> DRL order <], gens->nvars, */ gens->ngens, saturate, initial_hts, nr_threads, max_pairs, update_ht, la_option, use_signatures, 1 /* reduce_gb */, 0, info_level); bs = core_gba(bs, st, &error, 1073741831); if (!success || error) { printf("Problem with F4, stopped computation.\n"); return 104; } export_results_from_gba(bld, blen, bexp,bcf, &malloc, &bs, &bht, &st); int32_t *bcf_ff = (int32_t *)(*bcf); int32_t *bexp_lm = get_lead_monomials(bld, blen, bexp, gens); long dquot = 0; int32_t *lmb= monomial_basis (bld[0], gens->nvars, bexp_lm,&dquot); sp_matfglm_t *matrix= build_matrixn(lmb, dquot, bld[0], blen, bexp, bcf_ff,bexp_lm, gens->nvars, gens->field_char); /* display_fglm_matrix (stdout, matrix); */ if (matrix->charac != field_char) return 105; if (matrix->ncols != 11) return 106; if (matrix->nrows != 6) return 107; if (matrix->dense_mat[0] != 695220959) return 201; if (matrix->dense_mat[1] != 672652169) return 202; if (matrix->dense_mat[2] != 1046599061) return 203; if (matrix->dense_mat[3] != 260205064) return 204; if (matrix->dense_mat[4] != 787559341) return 205; if (matrix->dense_mat[5] != 635594395) return 206; if (matrix->dense_mat[6] != 82300796) return 207; if (matrix->dense_mat[7] != 148803321) return 208; if (matrix->dense_mat[8] != 155205489) return 209; if (matrix->dense_mat[9] != 638296297) return 210; if (matrix->dense_mat[10] != 873613310) return 211; if (matrix->dense_mat[11] != 344758724) return 212; if (matrix->dense_mat[12] != 836890318) return 213; if (matrix->dense_mat[13] != 158248818) return 214; if (matrix->dense_mat[14] != 105450484) return 215; if (matrix->dense_mat[15] != 676511729) return 216; if (matrix->dense_mat[16] != 165475628) return 217; if (matrix->dense_mat[17] != 674062047) return 218; if (matrix->dense_mat[18] != 386559681) return 219; if (matrix->dense_mat[19] != 291442961) return 220; if (matrix->dense_mat[20] != 579903534) return 221; if (matrix->dense_mat[21] != 141486867) return 222; if (matrix->dense_mat[22] != 572023784) return 223; if (matrix->dense_mat[23] != 744133717) return 224; if (matrix->dense_mat[24] != 348598510) return 225; if (matrix->dense_mat[25] != 468551107) return 226; if (matrix->dense_mat[26] != 842113423) return 227; if (matrix->dense_mat[27] != 659500774) return 228; if (matrix->dense_mat[28] != 733019635) return 229; if (matrix->dense_mat[29] != 1071125757) return 230; if (matrix->dense_mat[30] != 852888838) return 231; if (matrix->dense_mat[31] != 981635303) return 232; if (matrix->dense_mat[32] != 305324683) return 233; if (matrix->dense_mat[33] != 1039333228) return 234; if (matrix->dense_mat[34] != 1067654706) return 235; if (matrix->dense_mat[35] != 813998442) return 236; if (matrix->dense_mat[36] != 829655474) return 237; if (matrix->dense_mat[37] != 1054477649) return 238; if (matrix->dense_mat[38] != 100193860) return 239; if (matrix->dense_mat[39] != 106199953) return 240; if (matrix->dense_mat[40] != 1009183349) return 241; if (matrix->dense_mat[41] != 74459732) return 242; if (matrix->dense_mat[42] != 328387945) return 243; if (matrix->dense_mat[43] != 762192905) return 244; if (matrix->dense_mat[44] != 137100198) return 245; if (matrix->dense_mat[45] != 916451149) return 246; if (matrix->dense_mat[46] != 753995230) return 247; if (matrix->dense_mat[47] != 639147380) return 248; if (matrix->dense_mat[48] != 202835333) return 249; if (matrix->dense_mat[49] != 1020314720) return 250; if (matrix->dense_mat[50] != 173981585) return 251; if (matrix->dense_mat[51] != 37718888) return 252; if (matrix->dense_mat[52] != 471998822) return 253; if (matrix->dense_mat[53] != 911855634) return 254; if (matrix->dense_mat[54] != 877767489) return 255; if (matrix->dense_mat[55] != 620591546) return 256; if (matrix->dense_mat[56] != 346575422) return 257; if (matrix->dense_mat[57] != 5929868) return 258; if (matrix->dense_mat[58] != 99564914) return 259; if (matrix->dense_mat[59] != 141010962) return 260; if (matrix->dense_mat[60] != 1024131791) return 261; if (matrix->dense_mat[61] != 824205027) return 262; if (matrix->dense_mat[62] != 495749234) return 263; if (matrix->dense_mat[63] != 578054943) return 264; if (matrix->dense_mat[64] != 143011498) return 265; if (matrix->dense_mat[65] != 476740452) return 266; if (matrix->triv_idx[0] != 0) return 267; if (matrix->triv_idx[1] != 1) return 268; if (matrix->triv_idx[2] != 2) return 269; if (matrix->triv_idx[3] != 3) return 270; if (matrix->triv_idx[4] != 4) return 271; if (matrix->triv_pos[0] != 1) return 272; if (matrix->triv_pos[1] != 5) return 273; if (matrix->triv_pos[2] != 6) return 274; if (matrix->triv_pos[3] != 7) return 275; if (matrix->triv_pos[4] != 8) return 276; if (matrix->dense_idx[0] != 5) return 277; if (matrix->dense_idx[1] != 6) return 278; if (matrix->dense_idx[2] != 7) return 279; if (matrix->dense_idx[3] != 8) return 280; if (matrix->dense_idx[4] != 9) return 281; if (matrix->dense_idx[5] != 10) return 282; if (matrix->dst[0] != 0) return 283; if (matrix->dst[1] != 0) return 284; if (matrix->dst[2] != 0) return 285; if (matrix->dst[3] != 0) return 286; if (matrix->dst[4] != 0) return 287; if (matrix->dst[5] != 0) return 288; return 0; } msolve-0.6.5/test/fglm/build_matrixn_radical_shape-31.c000066400000000000000000000107641456710632100230350ustar00rootroot00000000000000#include "../../src/msolve/libmsolve.c" int main(void) { int32_t la_option = 2; // by default int32_t use_signatures = 0; int32_t nr_threads = 1; int32_t info_level = 0; int32_t initial_hts = 17; int32_t max_pairs = 0; int32_t elim_block_len = 0; int32_t update_ht = 0; int32_t generate_pbm = 0; int32_t reduce_gb = 1; int32_t print_gb = 0; int32_t genericity_handling = 2; int32_t saturate = 0; int32_t colon = 0; int32_t normal_form = 0; int32_t normal_form_matrix = 0; int32_t is_gb = 0; int32_t get_param = 0; int32_t precision = 128; int32_t refine = 0; /* not used at the moment */ int32_t isolate = 0; /* not used at the moment */ files_gb *files = malloc(sizeof(files_gb)); files->in_file = "input_files/radical_shape-31.ms"; files->out_file = NULL; FILE *fh = fopen(files->in_file, "r"); // int32_t mon_order = 0; int32_t nr_vars = 0; int32_t field_char = 9001; int32_t nr_gens = 0; data_gens_ff_t *gens = allocate_data_gens(); get_data_from_file(files->in_file, &nr_vars, &field_char,&nr_gens,gens); if (nr_vars != 3) return 101; if (field_char != 1073741827) return 102; if (nr_gens != 3) return 103; gens->rand_linear = 0; gens->random_linear_form = malloc(sizeof(int32_t)*(nr_vars)); param_t *param = NULL; mpz_param_t mpz_param; mpz_param_init(mpz_param); long nb_real_roots = 0; interval *real_roots = NULL; real_point_t *real_pts = NULL; param_t ** paramp = ¶m; mpz_param_t *mpz_paramp = &mpz_param; long *nb_real_roots_ptr = &nb_real_roots; interval **real_roots_ptr = &real_roots; real_point_t **real_pts_ptr = &real_pts; int32_t *bld = NULL; int32_t **blen = NULL; int32_t **bexp = NULL; void **bcf = NULL; int b = 0; /* counter for randomly chosen linear forms */ int round = -1; bld = malloc(sizeof(int32_t)); blen = malloc(sizeof(int32_t *)); bexp = malloc(sizeof(int32_t *)); bcf = malloc(sizeof(void *)); bs_t *bs = NULL; ht_t *bht = NULL; md_t *st = NULL; int success = 0; int32_t error = 0; success = initialize_gba_input_data(&bs, &bht, &st,gens->lens, gens->exps, (void *)gens->cfs, 1073741827, 0 /* DRL order */,elim_block_len, gens->nvars,/* gens->field_char,0 [> DRL order <], gens->nvars, */ gens->ngens, saturate, initial_hts, nr_threads, max_pairs, update_ht, la_option, use_signatures, 1 /* reduce_gb */, 0, info_level); bs = core_gba(bs, st, &error, 1073741827); if (!success || error) { printf("Problem with F4, stopped computation.\n"); return 104; } export_results_from_gba(bld, blen, bexp,bcf, &malloc, &bs, &bht, &st); int32_t *bcf_ff = (int32_t *)(*bcf); int32_t *bexp_lm = get_lead_monomials(bld, blen, bexp, gens); long dquot = 0; int32_t *lmb= monomial_basis (bld[0], gens->nvars, bexp_lm,&dquot); sp_matfglm_t *matrix= build_matrixn(lmb, dquot, bld[0], blen, bexp, bcf_ff,bexp_lm, gens->nvars, gens->field_char); /* display_fglm_matrix (stdout, matrix); */ if (matrix->charac != field_char) return 105; if (matrix->ncols != 4) return 106; if (matrix->nrows != 3) return 107; if (matrix->dense_mat[0] != 429496729) return 201; if (matrix->dense_mat[1] != 858993461) return 202; if (matrix->dense_mat[2] != 214748365) return 203; if (matrix->dense_mat[3] != 429496731) return 204; if (matrix->dense_mat[4] != 858993459) return 205; if (matrix->dense_mat[5] != 644245095) return 206; if (matrix->dense_mat[6] != 429496730) return 207; if (matrix->dense_mat[7] != 858993462) return 208; if (matrix->dense_mat[8] != 858993447) return 209; if (matrix->dense_mat[9] != 644245093) return 210; if (matrix->dense_mat[10] != 429496731) return 211; if (matrix->dense_mat[11] != 858993464) return 212; if (matrix->triv_idx[0] != 0) return 213; if (matrix->triv_pos[0] != 1) return 214; if (matrix->dense_idx[0] != 1) return 215; if (matrix->dense_idx[1] != 2) return 216; if (matrix->dense_idx[2] != 3) return 217; if (matrix->dst[0] != 0) return 218; if (matrix->dst[1] != 0) return 219; if (matrix->dst[2] != 0) return 220; return 0; } msolve-0.6.5/test/neogb/000077500000000000000000000000001456710632100151055ustar00rootroot00000000000000msolve-0.6.5/test/neogb/io/000077500000000000000000000000001456710632100155145ustar00rootroot00000000000000msolve-0.6.5/test/neogb/io/validate_input_data.c000066400000000000000000000032561456710632100216670ustar00rootroot00000000000000#include "../../../src/neogb/io.h" int main(void) { const int32_t lens[] = {2, 2}; const int32_t cfs[] = {1, -1, 1, -1}; uint32_t field_char = 32003; int32_t mon_order = 0; int32_t elim_block_len = 1; int32_t nr_vars = 2; int32_t nr_gens = 2; int32_t nr_nf = 1; /* must be <= nr_gens */ int32_t ht_size = 17; int32_t nr_threads = 1; int32_t max_nr_pairs = 0; int32_t reset_ht = 2; int32_t la_option = 45; /* incorrect: should be fixed to 2 */ int32_t use_signatures = 0; int32_t reduce_gb = -1; /* incorrect: should be fixed to 0 */ int32_t info_level = 2; int *invalid_gens = NULL; int res = validate_input_data(&invalid_gens, cfs, lens, &field_char, &mon_order, &elim_block_len, &nr_vars, &nr_gens, &nr_nf, &ht_size, &nr_threads, &max_nr_pairs, &reset_ht, &la_option, &use_signatures, &reduce_gb, &info_level); if (res == -1) return 1; if (res == 0) return 1; if (invalid_gens[0] != 0 || invalid_gens[1] != 0) return 1; if (field_char != 32003) return 1; if (mon_order != 0) return 1; if (elim_block_len != 1) return 1; if (nr_vars!= 2) return 1; if (nr_gens != 2) return 1; if (nr_nf != 1) return 1; if (ht_size != 17) return 1; if (nr_threads != 1) return 1; if (max_nr_pairs != 0) return 1; if (reset_ht != 2) return 1; if (la_option != 2) return 1; /* fixed */ if (use_signatures != 0) return 1; if (reduce_gb != 0) return 1; /* fixed */ if (info_level != 2) return 1; return 0; } msolve-0.6.5/test/scripts/000077500000000000000000000000001456710632100155025ustar00rootroot00000000000000msolve-0.6.5/test/scripts/fglm_build_matrixn.mpl000066400000000000000000000226521456710632100220710ustar00rootroot00000000000000with(Groebner): is_staircase_grevlex_generic:= proc (ns,rv,lmGb,vars) description "Check if the staircase ns is DRL-generic for the last variable " "of vars. Returns true if it is and false if it is not.": local xn,ns_sorted,lmGb_sorted, mon_ord, ind_ns,ind_lmGb,m,i,j,cmp: xn := vars[-1]: mon_ord:= tdeg (op(vars)): cmp := (a,b)->Groebner:-TestOrder (a,b,mon_ord): ns_sorted:= sort (ns,(a,b)->cmp (a,b)): lmGb_sorted:= sort (lmGb,(a,b)->cmp (a,b)): j:= 1: for i from 1 to nops (ns_sorted) do m:= ns[i]*xn: if (type (rv[m],indexed)) then if (m <> lmGb[j]) then printf ("%a goes out the staircase and does not land on " "a leading monomial\n",m): return false; else j:=j+1: end if: end if: end do: return true: end proc: ToMSolve:=proc(F, char, vars, fname) local i, fd, F2, str; fd:=fopen(fname, WRITE): for i from 1 to nops(vars)-1 do fprintf(fd, "%a, ", vars[i]): end; fprintf(fd, "%a ", vars[nops(vars)]): fprintf(fd,"\n"); fprintf(fd,"%d\n", char); if char = 0 then F2:=map(f->sort(expand(numer(f)), order=tdeg(op(vars))), F): F2:=remove(member, F2, [0]): for i from 1 to nops(F2)-1 do fprintf(fd, "%a,\n", F2[i]): od: fprintf(fd, "%a\n", F2[nops(F2)]): else F2:=map(f->sort(expand(numer(f)), order=tdeg(op(vars))) mod char, F): F2:=remove(member, F2, [0]): for i from 1 to nops(F2)-1 do fprintf(fd, "%a,\n", F2[i]): od: fprintf(fd, "%a\n", F2[nops(F2)]): fi: fclose(fd): # str := cat("sed -i -e ':a' -e 'N' -e '$!ba' -e 's/\\\n//g' ", fname): str := cat("sed -i -e ':a' -e 'N' -e '$!ba' -e 's/\\\\\\n//g' ", fname): system(str): end proc: main:= proc (F,vars,char,str) local G,lmGb,lmGbxn,ord,ns,rv,fd,b,i,i2,j,nr_col,nr_row: local dense_idx,triv_idx,triv_pos,Mxn,dst,cpt; ord := tdeg(op(vars)): G := Groebner:-Basis (F,ord,characteristic=char): lmGb := map (g->LeadingMonomial (g,ord), G): lmGbxn:= select (g->degree (g,vars[-1])>0,lmGb): nr_row:= nops(lmGbxn): ns,rv:= NormalSet (G,ord): nr_col:= nops(ns): triv_idx:= [seq (i,i=1..nr_col)]: dense_idx,triv_idx:= selectremove (l->type(rv[ns[l]*vars[-1]],indexed), triv_idx): triv_pos:= map (l->rv[ns[l]*vars[-1]],triv_idx): dst:= map (l->0,dense_idx): ToMSolve (F,char,vars,cat("../input_files/",str,".ms")): fd:= fopen (cat("../fglm/build_matrixn_",str,".c"),WRITE): cpt: fprintf (fd, "#include \"../../src/msolve/libmsolve.c\"\n\n" "int main(void)\n{\n" " int32_t la_option = 2; // by default\n" " int32_t use_signatures = 0;\n" " int32_t nr_threads = 1;\n" " int32_t info_level = 0;\n" " int32_t initial_hts = 17;\n" " int32_t max_pairs = 0;\n" " int32_t elim_block_len = 0;\n" " int32_t update_ht = 0;\n" " int32_t generate_pbm = 0;\n" " int32_t reduce_gb = 1;\n" " int32_t print_gb = 0;\n" " int32_t genericity_handling = 2;\n" " int32_t saturate = 0;\n" " int32_t colon = 0;\n" " int32_t normal_form = 0;\n" " int32_t normal_form_matrix = 0;\n" " int32_t is_gb = 0;\n" " int32_t get_param = 0;\n" " int32_t precision = 128;\n" " int32_t refine = 0; /* not used at the moment */\n" " int32_t isolate = 0; /* not used at the moment */\n" " files_gb *files = malloc(sizeof(files_gb));\n" " files->in_file = \"test/input_files/%s.ms\";\n" " files->out_file = NULL;\n" " FILE *fh = fopen(files->in_file, \"r\");\n\n" " // int32_t mon_order = 0;\n" " int32_t nr_vars = 0;\n" " int32_t field_char = 9001;\n" " int32_t nr_gens = 0;\n" " data_gens_ff_t *gens = allocate_data_gens();\n\n" " get_data_from_file(files->in_file, &nr_vars, &field_char,&nr_gens,gens);\n\n" " if (nr_vars != %a) return 101;\n" " if (field_char != %a) return 102;\n" " if (nr_gens != %a) return 103;\n\n" " gens->rand_linear = 0;\n" " gens->random_linear_form = malloc(sizeof(int32_t)*(nr_vars));\n\n" " param_t *param = NULL;\n" " mpz_param_t mpz_param;\n" " mpz_param_init(mpz_param);\n\n" " long nb_real_roots = 0;\n" " interval *real_roots = NULL;\n" " real_point_t *real_pts = NULL;\n\n" " param_t ** paramp = ¶m;\n" " mpz_param_t *mpz_paramp = &mpz_param;\n" " long *nb_real_roots_ptr = &nb_real_roots;\n" " interval **real_roots_ptr = &real_roots;\n" " real_point_t **real_pts_ptr = &real_pts;\n\n" " int32_t *bld = NULL;\n" " int32_t **blen = NULL;\n" " int32_t **bexp = NULL;\n" " void **bcf = NULL;\n" " int b = 0;\n" " /* counter for randomly chosen linear forms */\n" " int round = -1;\n\n" " bld = malloc(sizeof(int32_t));\n" " blen = malloc(sizeof(int32_t *));\n" " bexp = malloc(sizeof(int32_t *));\n" " bcf = malloc(sizeof(void *));\n\n" " bs_t *bs = NULL;\n" " ht_t *bht = NULL;\n" " stat_t *st = NULL;\n\n" " int success = 0;\n\n" " success = initialize_gba_input_data(&bs, &bht, &st,gens->lens, gens->exps, (void *)gens->cfs, %a, 0 /* DRL order */,elim_block_len, gens->nvars,/* gens->field_char,0 [> DRL order <], gens->nvars, */ gens->ngens, saturate, initial_hts, nr_threads, max_pairs, update_ht, la_option, use_signatures, 1 /* reduce_gb */, 0, info_level);\n" " success = core_gba(&bs, &bht, &st);\n" " if (!success) {\n" " printf(\"Problem with F4, stopped computation.\\n\");\n" " return 104;\n" " }\n\n" " export_results_from_gba(bld, blen, bexp,bcf, &malloc, &bs, &bht, &st);\n\n" " int32_t *bcf_ff = (int32_t *)(*bcf);\n" " int32_t *bexp_lm = get_lead_monomials(bld, blen, bexp, gens);\n" " long dquot = 0;\n" " int32_t *lmb= monomial_basis (bld[0], gens->nvars, bexp_lm,&dquot);\n" " sp_matfglm_t *matrix= build_matrixn(lmb, dquot, bld[0], blen, bexp, bcf_ff,bexp_lm, gens->nvars, gens->field_char);\n\n" " /* display_fglm_matrix (stdout, matrix); */\n\n" " if (matrix->charac != field_char) return 105;\n" " if (matrix->ncols != %a) return 106;\n" " if (matrix->nrows != %a) return 107;\n\n", str,nops(vars),char,nops(F),char,nr_col,nr_row): b := is_staircase_grevlex_generic (ns,rv,lmGbxn,vars): cpt := 201: if (b) then Mxn := MultiplicationMatrix (vars[-1],ns,rv,G,ord,characteristic=char): print (Mxn); for i from 1 to nr_row do i2:= rv[lmGbxn[i]/vars[-1]]: for j from 1 to nr_col do fprintf (fd, " if (matrix->dense_mat[%a] != %a) return %a;\n", (i-1)*nr_col+j-1,Mxn[i2,j],cpt): cpt:= cpt+1: end do: for j from nr_col to 1 by -1 do if (Mxn[i2,j] = 0) then dst[i]:= dst[i]+1: else break; end if: end do: end do: fprintf (fd,"\n"): for i from 1 to nops(triv_idx) do fprintf (fd, " if (matrix->triv_idx[%a] != %a) return %a;\n", i-1,triv_idx[i]-1,cpt): cpt:= cpt+1: end do: for i from 1 to nops(triv_idx) do fprintf (fd, " if (matrix->triv_pos[%a] != %a) return %a;\n", i-1,triv_pos[i]-1,cpt): cpt:= cpt+1: end do: fprintf (fd,"\n"): for i from 1 to nr_row do fprintf (fd, " if (matrix->dense_idx[%a] != %a) return %a;\n", i-1,dense_idx[i]-1,cpt): cpt:=cpt+1: end do: fprintf (fd,"\n"): for i from 1 to nr_row do fprintf (fd, " if (matrix->dst[%a] != %a) return %a;\n", i-1,dst[i],cpt): cpt:=cpt+1: end do: fprintf (fd,"\n" " return 0;\n}"): end if: fclose (fd): printf ("Writing over\n"): end proc: trace(main): # F:=[x - 2*z^3 - 3*z^2 - 5*z - 7, # y - z^3 + z^2 - z + 1, # z^4 - z^3 - z^2 - z - 1 # ]: # vars:=[x,y,z]: # char:=1073741827: # str:="fglm_test": # main (F,vars,char,str): msolve-0.6.5/test/scripts/nonradical_radicalshape-31.mpl000066400000000000000000000002761456710632100232540ustar00rootroot00000000000000read "fglm_build_matrixn.mpl": char:= nextprime (2^30): vars:= [x,y]: F:= subs ({x=4578*x+789*y,y=1453*x+977*y},[x^2,x*y,y^2]): str:= "nonradical_radicalshape-31": main (F,vars,char,str); msolve-0.6.5/test/scripts/nonradical_shape-31.mpl000066400000000000000000000015111456710632100217250ustar00rootroot00000000000000read "fglm_build_matrixn.mpl": char:= nextprime (nextprime (2^30)): vars:= [seq (cat (x,i),i=1..4)]: F:= [570511439*x4^11+353378708*x4^10+599390609*x4^9+1049120212*x4^8+826752179*x4^7+19533939*x4^6+45047444*x4^5+448227342*x4^4+74356583*x4^3+17844919*x4^2+627145600*x4+ 372416000, x1+735241234*x4^10+884961191*x4^9+136721026*x4^8+198304612*x4^7+640439652*x4^6+417177801*x4^5+836782561*x4^4+537655879*x4^3+147944788*x4^2+702680360*x4+540721923, x2+904966252*x4^10+698412071*x4^9+618307600*x4^8+511091141*x4^7+316773880*x4^6+366222184*x4^5+961264978*x4^4+76338300*x4^3+25585315*x4^2+855028007*x4+347706282, x3+290319951*x4^10+366206486*x4^9+405889704*x4^8+213561267*x4^7+999862911*x4^6+838518850*x4^5+772320120*x4^4+264387201*x4^3+893645500*x4^2+x3+291291731*x4+117559519]: str:= "nonradical_shape-31": main (F,vars,char,str); msolve-0.6.5/test/scripts/radical_shape-31.mpl000066400000000000000000000003371456710632100212170ustar00rootroot00000000000000read "fglm_build_matrixn.mpl": char:= 1073741827: vars:= [x,y,z]: F:= [x - 2*z^3 - 3*z^2 - 5*z - 7, y - z^3 + z^2 - z + 1, z^4 - z^3 - z^2 - z - 1]: str:= "radical_shape-31": main (F,vars,char,str);